[m-dev.] for review: tuples [2]

Simon Taylor stayl at cs.mu.OZ.AU
Tue Aug 1 14:16:22 AEST 2000


Index: library/std_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/std_util.m,v
retrieving revision 1.194
diff -u -u -r1.194 std_util.m
--- library/std_util.m	2000/07/18 00:46:19	1.194
+++ library/std_util.m	2000/08/01 02:56:39
@@ -430,6 +430,11 @@
 :- func construct(type_desc, int, list(univ)) = univ.
 :- mode construct(in, in, in) = out is semidet.
 
+	% construct_tuple(Args) = Term
+	%
+	% Returns a tuple whose arguments are given by Args.
+:- func construct_tuple(list(univ)) = univ.
+
 %-----------------------------------------------------------------------------%
 
 	% functor, argument and deconstruct take any type (including univ),
@@ -451,6 +456,7 @@
 	%	  quotation marks
 	%	- for predicates and functions, the string
 	%	  <<predicate>>
+	%	- for tuples, the string {}
 
 	% functor(Data, Functor, Arity)
 	%
@@ -470,8 +476,8 @@
 	% Argument to that argument of the functor of the data item. If
 	% the argument index is out of range -- that is, greater than or
 	% equal to the arity of the functor or lower than 0 -- then
-	% the call fails.  For argument/1 the argument returned has the
-	% type univ, which can store any type.  For arg/1, if the
+	% the call fails.  For argument/2 the argument returned has the
+	% type univ, which can store any type.  For arg/2, if the
 	% argument has the wrong type, then the call fails.
 	% (Both abort if the type of Data is a type with a non-canonical
 	% representation, i.e. one for which there is a user-defined
@@ -1217,12 +1223,13 @@
 ** Values of type `std_util:type_ctor_desc' are not guaranteed to be
 ** represented the same way as values of type `private_builtin:type_ctor_info'.
 ** The representations *are* in fact identical for first order types, but they
-** differ for higher order types. Instead of a type_ctor_desc being a structure
-** containing a pointer to the type_ctor_info for pred/0 or func/0 and an
-** arity, we have a single small encoded integer. This integer is double
-** the arity, plus zero or one; plus zero encodes a predicate, plus one encodes
-** a function.  The maximum arity that can be encoded is given by
-** MR_MAX_HO_ARITY (see below).
+** differ for higher order and tuple types. Instead of a type_ctor_desc
+** being a structure containing a pointer to the type_ctor_info for pred/0
+** or func/0 and an arity, we have a single small encoded integer. This
+** integer is four times the arity, plus zero, one or two; plus zero encodes a
+** tuple, plus one encodes a predicate, plus two encodes a function.
+** The maximum arity that can be encoded is given by MR_MAX_VARIABLE_ARITY
+** (see below).
 ** The C type corresponding to std_util:type_ctor_desc is `MR_TypeCtorInfo'.
 */
 
@@ -1243,51 +1250,64 @@
 ** number of general purpose registers, since an predicate or function having
 ** more arguments that this would run out of registers when passing the input
 ** arguments, or the output arguments, or both.
+**
+** XXX When tuples were added this was reduced to be the maximum number
+** of general purpose registers, to reduce the probability that the
+** `small' integers for higher-order and tuple types are confused with
+** type_ctor_info pointers. This still allows higher-order terms with
+** 1024 arguments, which is more than ../LIMITATIONS promises.
 */
-#define MR_MAX_HO_ARITY         (2 * MAX_VIRTUAL_REG)
+#define MR_MAX_VARIABLE_ARITY         MAX_VIRTUAL_REG
 
 /*
 ** Constructors for the MR_TypeCtorDesc ADT
 */
+
 #define MR_TYPECTOR_DESC_MAKE_PRED(Arity)                               \
-        ( (MR_TypeCtorDesc) ((Arity) * 2) )
+        ( (MR_TypeCtorDesc) ((Arity) * 4) )
 #define MR_TYPECTOR_DESC_MAKE_FUNC(Arity)                               \
-        ( (MR_TypeCtorDesc) ((Arity) * 2 + 1) )
-#define MR_TYPECTOR_DESC_MAKE_FIRST_ORDER(type_ctor_info)               \
-        ( MR_CHECK_EXPR_TYPE(type_ctor_info, MR_TypeCtorInfo),		\
-	  (MR_TypeCtorDesc) type_ctor_info )
+        ( (MR_TypeCtorDesc) ((Arity) * 4 + 1) )
+#define MR_TYPECTOR_DESC_MAKE_TUPLE(Arity)                              \
+        ( (MR_TypeCtorDesc) ((Arity) * 4 + 2) )
+#define MR_TYPECTOR_DESC_MAKE_FIXED_ARITY(type_ctor_info)               \
+        ( MR_CHECK_EXPR_TYPE(type_ctor_info, MR_TypeCtorInfo),          \
+          (MR_TypeCtorDesc) type_ctor_info )
 
 /*
 ** Access macros for the MR_TypeCtor ADT.
 **
-** The MR_TYPECTOR_DESC_GET_HOT_* macros should only be called if
-** MR_TYPECTOR_DESC_IS_HIGHER_ORDER() returns true.
-** The MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO() macro
-** should only be called if MR_TYPECTOR_DESC_IS_HIGHER_ORDER() returns false.
+** The MR_TYPECTOR_DESC_GET_VA_* macros should only be called if
+** MR_TYPECTOR_DESC_IS_VARIABLE_ARITY() returns true.
+** The MR_TYPECTOR_DESC_GET_FIXED_ARITY_TYPE_CTOR_INFO() macro
+** should only be called if MR_TYPECTOR_DESC_IS_VARIABLE_ARITY() returns false.
 */
-#define MR_TYPECTOR_DESC_IS_HIGHER_ORDER(T)                             \
-        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),			\
-          (Unsigned) (T) <= (2 * MR_MAX_HO_ARITY + 1) )
-#define MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO(T)              \
-        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),			\
-	  (MR_TypeCtorInfo) (T) )
-#define MR_TYPECTOR_DESC_GET_HOT_ARITY(T)                               \
-        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),			\
-          (Unsigned) (T) / 2 )
-#define MR_TYPECTOR_DESC_GET_HOT_NAME(T)                                \
-        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),			\
-          (ConstString) (((Unsigned) (T) % 2 != 0)         		\
-                ? ""func""                                              \
-                : ""pred"" ))
-#define MR_TYPECTOR_DESC_GET_HOT_MODULE_NAME(T)                         \
-        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),			\
+#define MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(T)                           \
+        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),                       \
+          (Unsigned) (T) <= (4 * MR_MAX_VARIABLE_ARITY + 2) )
+#define MR_TYPECTOR_DESC_GET_FIXED_ARITY_TYPE_CTOR_INFO(T)              \
+        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),                       \
+          (MR_TypeCtorInfo) (T) )
+#define MR_TYPECTOR_DESC_GET_VA_ARITY(T)                                \
+        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),                       \
+          (Unsigned) (T) / 4 )
+#define MR_TYPECTOR_DESC_GET_VA_NAME(T)                                 \
+        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),                       \
+          (ConstString) (((Unsigned) (T) % 4 == 0)                      \
+                ? ""pred""                                              \
+                : (((Unsigned) (T) % 4 == 1)                            \
+                    ? ""func""                                          \
+                    : ""{}"" )) )
+#define MR_TYPECTOR_DESC_GET_VA_MODULE_NAME(T)                          \
+        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),                       \
           (ConstString) ""builtin"" )
-#define MR_TYPECTOR_DESC_GET_HOT_TYPE_CTOR_INFO(T)                      \
-        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),			\
-          ((Unsigned) (T) % 2 != 0)      				\
-                ? MR_TYPE_CTOR_INFO_HO_FUNC				\
-                : MR_TYPE_CTOR_INFO_HO_PRED )
-		
+#define MR_TYPECTOR_DESC_GET_VA_TYPE_CTOR_INFO(T)                       \
+        ( MR_CHECK_EXPR_TYPE(T, MR_TypeCtorDesc),                       \
+          ((Unsigned) (T) % 4 == 0)                                     \
+                ? MR_TYPE_CTOR_INFO_HO_PRED                             \
+                : (((Unsigned) (T) % 4 == 1)                            \
+                   ? MR_TYPE_CTOR_INFO_HO_FUNC                          \
+                   : MR_TYPE_CTOR_INFO_TUPLE ) )
+
 #endif /* ML_TYPECTORDESC_GUARD */
 
 ").
@@ -1381,6 +1401,13 @@
 		 	IsFunc = no
 		),
 		(
+			ModuleName = "builtin", Name = "{}"
+		->
+			type_arg_names(ArgTypes, IsFunc, ArgTypeNames),
+			list__append(ArgTypeNames, ["}"], TypeStrings0),
+			TypeStrings = ["{" | TypeStrings0],
+			string__append_list(TypeStrings, UnqualifiedTypeName)
+		;
 			IsFunc = yes,
 			ArgTypes = [FuncRetType]
 		->
@@ -1469,19 +1496,26 @@
 	if (MR_TYPE_CTOR_INFO_IS_HO_PRED(type_ctor_info)) {
 		type_ctor_desc = MR_TYPECTOR_DESC_MAKE_PRED(
 			MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info));
-		if (! MR_TYPECTOR_DESC_IS_HIGHER_ORDER(type_ctor_desc)) {
+		if (! MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(type_ctor_desc)) {
 			MR_fatal_error(""std_util:ML_make_type_ctor_desc""
 				""- arity out of range."");
 		}
 	} else if (MR_TYPE_CTOR_INFO_IS_HO_FUNC(type_ctor_info)) {
 		type_ctor_desc = MR_TYPECTOR_DESC_MAKE_FUNC(
 			MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info));
-		if (! MR_TYPECTOR_DESC_IS_HIGHER_ORDER(type_ctor_desc)) {
+		if (! MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(type_ctor_desc)) {
 			MR_fatal_error(""std_util:ML_make_type_ctor_desc""
 				""- arity out of range."");
 		}
+	} else if (MR_TYPE_CTOR_INFO_IS_TUPLE(type_ctor_info)) {
+		type_ctor_desc = MR_TYPECTOR_DESC_MAKE_TUPLE(
+			MR_TYPEINFO_GET_TUPLE_ARITY(type_info));
+		if (! MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(type_ctor_desc)) {
+			MR_fatal_error(""std_util:ML_make_type_ctor_desc""
+				""- arity out of range."");
+		}
 	} else {
-		type_ctor_desc = MR_TYPECTOR_DESC_MAKE_FIRST_ORDER(
+		type_ctor_desc = MR_TYPECTOR_DESC_MAKE_FIXED_ARITY(
 			type_ctor_info);
 	}
 
@@ -1506,8 +1540,9 @@
 	type_ctor_desc = ML_make_type_ctor_desc(type_info, type_ctor_info);
 	*type_ctor_desc_ptr = type_ctor_desc;
 
-	if (type_ctor_info->type_ctor_rep == MR_TYPECTOR_REP_PRED) {
-		arity = MR_TYPECTOR_DESC_GET_HOT_ARITY(type_ctor_desc);
+	if (MR_type_ctor_rep_is_variable_arity(type_ctor_info->type_ctor_rep))
+	{
+		arity = MR_TYPECTOR_DESC_GET_VA_ARITY(type_ctor_desc);
 		*arg_type_info_list_ptr = ML_type_params_vector_to_list(arity,
 			MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(type_info));
 	} else {
@@ -1552,10 +1587,10 @@
 
 	type_ctor_desc = (MR_TypeCtorDesc) TypeCtorDesc;
 
-	if (MR_TYPECTOR_DESC_IS_HIGHER_ORDER(type_ctor_desc)) {
-		arity = MR_TYPECTOR_DESC_GET_HOT_ARITY(type_ctor_desc);
+	if (MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(type_ctor_desc)) {
+		arity = MR_TYPECTOR_DESC_GET_VA_ARITY(type_ctor_desc);
 	} else {
-        type_ctor_info = MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO(
+        type_ctor_info = MR_TYPECTOR_DESC_GET_FIXED_ARITY_TYPE_CTOR_INFO(
             type_ctor_desc);
 		arity = type_ctor_info->arity;
 	}
@@ -1602,16 +1637,16 @@
 
 	type_ctor_desc = (MR_TypeCtorDesc) TypeCtorDesc;
 
-	if (MR_TYPECTOR_DESC_IS_HIGHER_ORDER(type_ctor_desc)) {
+	if (MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(type_ctor_desc)) {
 		TypeCtorModuleName = (String) (Word)
-			MR_TYPECTOR_DESC_GET_HOT_MODULE_NAME(type_ctor_desc);
+			MR_TYPECTOR_DESC_GET_VA_MODULE_NAME(type_ctor_desc);
 		TypeCtorName = (String) (Word)
-			MR_TYPECTOR_DESC_GET_HOT_NAME(type_ctor_desc);
-		TypeCtorArity = MR_TYPECTOR_DESC_GET_HOT_ARITY(type_ctor_desc);
+			MR_TYPECTOR_DESC_GET_VA_NAME(type_ctor_desc);
+		TypeCtorArity = MR_TYPECTOR_DESC_GET_VA_ARITY(type_ctor_desc);
 	} else {
         MR_TypeCtorInfo type_ctor_info;
 
-        type_ctor_info = MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO(
+        type_ctor_info = MR_TYPECTOR_DESC_GET_FIXED_ARITY_TYPE_CTOR_INFO(
             type_ctor_desc);
 
             /*
@@ -1669,12 +1704,22 @@
                 construct_info.functor_name);
         arity = construct_info.arity;
         Arity = arity;
-        save_transient_registers();
-        TypeInfoList = ML_pseudo_type_info_vector_to_type_info_list(
-            arity,
-            MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info),
-            construct_info.arg_pseudo_type_infos);
-        restore_transient_registers();
+
+        if (MR_TYPE_CTOR_INFO_IS_TUPLE(
+                        MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info)))
+        {
+            save_transient_registers();
+            TypeInfoList = ML_type_params_vector_to_list(Arity,
+                    MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info));
+            restore_transient_registers();
+        } else {
+            save_transient_registers();
+            TypeInfoList = ML_pseudo_type_info_vector_to_type_info_list(
+                arity,
+                MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info),
+                construct_info.arg_pseudo_type_infos);
+            restore_transient_registers();
+        }
     }
     SUCCESS_INDICATOR = success;
 }
@@ -1713,6 +1758,7 @@
         case MR_TYPECTOR_REP_NOTAG_USEREQ:
         case MR_TYPECTOR_REP_NOTAG_GROUND:
         case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
+        case MR_TYPECTOR_REP_TUPLE:
             Ordinal = 0;
             break;
 
@@ -1850,6 +1896,30 @@
             }
             break;
 
+        case MR_TYPECTOR_REP_TUPLE:
+            {
+                int     arity, i;
+                Word    arg_list;
+
+                arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+    
+                incr_hp_msg(new_data, arity, MR_PROC_LABEL,
+                    ""<created by std_util:construct/3>"");
+    
+                arg_list = ArgList;
+                for (i = 0; i < arity; i++) {
+                    MR_field(MR_mktag(0), new_data, i) =
+                        MR_field(MR_mktag(0), MR_list_head(arg_list),
+                            UNIV_OFFSET_FOR_DATA);
+                    arg_list = MR_list_tail(arg_list);
+                }
+
+                if (! MR_list_is_empty(arg_list)) {
+                    MR_fatal_error(""excess arguments in std_util:construct"");
+                }
+            }
+            break;
+
         default:
             MR_fatal_error(""bad type_ctor_rep in std_util:construct"");
         }
@@ -1869,6 +1939,50 @@
 }
 ").
 
+construct_tuple(Args) =
+	construct_tuple_2(Args,
+		list__map(univ_type, Args),
+		list__length(Args)).
+
+:- func construct_tuple_2(list(univ), list(type_desc), int) = univ.
+
+:- pragma c_code(construct_tuple_2(Args::in, ArgTypes::in,
+		Arity::in) = (Term::out),
+		will_not_call_mercury, "
+{
+	MR_TypeInfo type_info;
+	Word new_data;
+	Word arg_value;
+	int i;
+
+	/*
+	** Construct a type_info for the tuple.
+	*/
+	type_info = ML_make_type(Arity, MR_TYPECTOR_DESC_MAKE_TUPLE(Arity),
+			ArgTypes);
+
+	/*
+	** Create the tuple.
+	*/
+	incr_hp_msg(new_data, Arity, MR_PROC_LABEL,
+		""<created by std_util:construct_tuple/1>"");
+	for (i = 0; i < Arity; i++) {
+		arg_value = MR_field(MR_mktag(0), MR_list_head(Args),
+				UNIV_OFFSET_FOR_DATA);
+		MR_field(MR_mktag(0), new_data, i) = arg_value;
+		Args = MR_list_tail(Args);
+	}
+
+	/*
+	** Create a univ.
+	*/
+	incr_hp_msg(Term, 2, MR_PROC_LABEL, ""std_util:univ/0"");
+	MR_field(MR_mktag(0), Term, UNIV_OFFSET_FOR_TYPEINFO) =
+		(Word) type_info;
+	MR_field(MR_mktag(0), Term, UNIV_OFFSET_FOR_DATA) = new_data;
+}
+").
+
 :- pragma c_code("
 
     /*
@@ -1980,6 +2094,14 @@
         MR_fatal_error(""unexpected EQUIV_VAR type_ctor_rep"");
         break;
 
+    case MR_TYPECTOR_REP_TUPLE:
+        construct_info->functor_name = ""{}"";
+        construct_info->arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+
+        /* Tuple types don't have pseudo-type_infos for the functors. */
+        construct_info->arg_pseudo_type_infos = NULL;
+        break;
+
     case MR_TYPECTOR_REP_INT:
     case MR_TYPECTOR_REP_CHAR:
     case MR_TYPECTOR_REP_FLOAT:
@@ -2043,9 +2165,15 @@
         list_arg_type_info = (MR_TypeInfo) MR_field(MR_mktag(0),
             MR_list_head(arg_list), UNIV_OFFSET_FOR_TYPEINFO);
 
-        arg_type_info = MR_create_type_info(
-            MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info),
-            arg_pseudo_type_infos[i]);
+        if (MR_TYPE_CTOR_INFO_IS_TUPLE(
+                MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info)))
+        {
+            arg_type_info = MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info)[i + 1];
+        } else {
+            arg_type_info = MR_create_type_info(
+                MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info),
+                arg_pseudo_type_infos[i]);
+        }
 
         comp = MR_compare_type_info(list_arg_type_info, arg_type_info);
         if (comp != MR_COMPARE_EQUAL) {
@@ -2106,22 +2234,22 @@
     int             i;
 
     /*
-    ** We need to treat higher-order predicates as a special case here.
+    ** We need to treat higher-order and tuple types as a special case here.
     */
 
-    if (MR_TYPECTOR_DESC_IS_HIGHER_ORDER(type_ctor_desc)) {
-        type_ctor_info = MR_TYPECTOR_DESC_GET_HOT_TYPE_CTOR_INFO(
+    if (MR_TYPECTOR_DESC_IS_VARIABLE_ARITY(type_ctor_desc)) {
+        type_ctor_info = MR_TYPECTOR_DESC_GET_VA_TYPE_CTOR_INFO(
             type_ctor_desc);
 
         restore_transient_registers();
         incr_hp_atomic_msg(LVALUE_CAST(Word, new_type_info_arena),
             MR_higher_order_type_info_size(arity),
-	    ""mercury__std_util__ML_make_type"", ""type_info"");
+            ""mercury__std_util__ML_make_type"", ""type_info"");
         save_transient_registers();
         MR_fill_in_higher_order_type_info(new_type_info_arena,
             type_ctor_info, arity, new_type_info_args);
     } else {
-        type_ctor_info = MR_TYPECTOR_DESC_GET_FIRST_ORDER_TYPE_CTOR_INFO(
+        type_ctor_info = MR_TYPECTOR_DESC_GET_FIXED_ARITY_TYPE_CTOR_INFO(
             type_ctor_desc);
 
         if (arity == 0) {
@@ -2131,7 +2259,7 @@
         restore_transient_registers();
         incr_hp_atomic_msg(LVALUE_CAST(Word, new_type_info_arena),
             MR_first_order_type_info_size(arity),
-	    ""mercury__std_util__ML_make_type"", ""type_info"");
+            ""mercury__std_util__ML_make_type"", ""type_info"");
         save_transient_registers();
         MR_fill_in_first_order_type_info(new_type_info_arena,
             type_ctor_info, new_type_info_args);
@@ -2274,6 +2402,7 @@
         case MR_TYPECTOR_REP_NOTAG_USEREQ:
         case MR_TYPECTOR_REP_NOTAG_GROUND:
         case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
+        case MR_TYPECTOR_REP_TUPLE:
             functors = 1;
             break;
 
@@ -2366,6 +2495,7 @@
     int         num_extra_args;
     Word        *arg_values;
     MR_TypeInfo *arg_type_infos;
+    bool        can_free_arg_type_infos;
     bool        non_canonical_type;
     bool        need_functor;
     bool        need_args;
@@ -2431,6 +2561,7 @@
 
     type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
     expand_info->non_canonical_type = FALSE;
+    expand_info->can_free_arg_type_infos = FALSE;
 
     switch(type_ctor_info->type_ctor_rep) {
 
@@ -2504,6 +2635,7 @@
                     int i;
 
                     expand_info->arg_values = arg_vector;
+                    expand_info->can_free_arg_type_infos = TRUE;
                     expand_info->arg_type_infos = MR_GC_NEW_ARRAY(MR_TypeInfo,
                         expand_info->arity);
 
@@ -2542,6 +2674,7 @@
 
             if (expand_info->need_args) {
                 expand_info->arg_values = data_word_ptr;
+                expand_info->can_free_arg_type_infos = TRUE;
                 expand_info->arg_type_infos = MR_GC_NEW_ARRAY(MR_TypeInfo, 1);
                 expand_info->arg_type_infos[0] = MR_create_type_info(
                     MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info),
@@ -2566,6 +2699,7 @@
 
             if (expand_info->need_args) {
                 expand_info->arg_values = data_word_ptr;
+                expand_info->can_free_arg_type_infos = TRUE;
                 expand_info->arg_type_infos = MR_GC_NEW_ARRAY(MR_TypeInfo, 1);
                 expand_info->arg_type_infos[0] =
                     MR_pseudo_type_info_is_ground(type_ctor_info->
@@ -2688,6 +2822,25 @@
             expand_info->num_extra_args = 0;
             break;
 
+        case MR_TYPECTOR_REP_TUPLE:
+            expand_info->arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+            expand_info->num_extra_args = 0;
+
+            if (expand_info->need_functor) {
+                MR_make_aligned_string(expand_info->functor, ""{}"");
+            }
+            if (expand_info->need_args) {
+                expand_info->arg_values = (Word *) *data_word_ptr;
+
+                /*
+                ** Type-infos are normally counted from one, but
+                ** the users of this vector count from zero.
+                */
+                expand_info->arg_type_infos =
+                        MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info) + 1;
+            }
+            break;
+
         case MR_TYPECTOR_REP_UNIV: {
             Word    data_word;
                 /*
@@ -2888,7 +3041,9 @@
     ** the stuff we want out of it.
     */
 
-    MR_GC_free(expand_info.arg_type_infos);
+    if (expand_info.can_free_arg_type_infos) {
+        MR_GC_free(expand_info.arg_type_infos);
+    }
 
     return success;
 }
@@ -3081,8 +3236,9 @@
     ** all its arguments onto the heap.
     */
 
-    MR_GC_free(expand_info.arg_type_infos);
-
+    if (expand_info.can_free_arg_type_infos) {
+        MR_GC_free(expand_info.arg_type_infos);
+    }
 }").
 
 %-----------------------------------------------------------------------------%
Index: library/term_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/term_io.m,v
retrieving revision 1.58
diff -u -u -r1.58 term_io.m
--- library/term_io.m	1999/06/09 14:19:09	1.58
+++ library/term_io.m	2000/07/22 23:54:19
@@ -235,6 +235,14 @@
 		term_io__write_term_2(BracedTerm, VarSet0, N0, VarSet, N),
 		io__write_string(" }")
 	;
+		{ Functor = term__atom("{}") },
+		{ Args = [BracedHead | BracedTail] }
+	->
+		io__write_char('{'),
+		term_io__write_arg_term(BracedHead, VarSet0, N0, VarSet1, N1),
+		term_io__write_term_args(BracedTail, VarSet1, N1, VarSet, N),
+		io__write_char('}')
+	;
 		% the empty functor '' is used for higher-order syntax:
 		% Var(Arg, ...) gets parsed as ''(Var, Arg).  When writing
 		% it out, we want to use the nice syntax.
Index: profiler/demangle.m
===================================================================
RCS file: /home/mercury1/repository/mercury/profiler/demangle.m,v
retrieving revision 1.9
diff -u -u -r1.9 demangle.m
--- profiler/demangle.m	1999/06/15 07:10:14	1.9
+++ profiler/demangle.m	2000/07/26 04:59:54
@@ -490,6 +490,8 @@
 		insert_prefix(";")
 	; remove_prefix("f_cut") ->
 		insert_prefix("!")
+	; remove_prefix("f_tuple") ->
+		insert_prefix("{}")
 	; remove_prefix("f_") ->
 		fix_mangled_ascii_chars
 	;
Index: runtime/mercury.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury.c,v
retrieving revision 1.8
diff -u -u -r1.8 mercury.c
--- runtime/mercury.c	2000/07/20 10:39:35	1.8
+++ runtime/mercury.c	2000/08/01 02:17:26
@@ -80,6 +80,7 @@
 
 static MR_UnifyFunc_1
 	mercury__array__do_unify__array_1_0,
+	mercury__builtin__do_unify__tuple_0_0,
 	mercury__private_builtin__do_unify__type_ctor_info_1_0,
 	mercury__private_builtin__do_unify__type_info_1_0,
 	mercury__private_builtin__do_unify__typeclass_info_1_0,
@@ -99,6 +100,7 @@
 
 static MR_CompareFunc_1
 	mercury__array__do_compare__array_1_0,
+	mercury__builtin__do_compare__tuple_0_0,
 	mercury__private_builtin__do_compare__type_ctor_info_1_0,
 	mercury__private_builtin__do_compare__type_info_1_0,
 	mercury__private_builtin__do_compare__typeclass_info_1_0,
@@ -168,6 +170,7 @@
 MR_define_type_ctor_info(builtin, c_pointer, 0, MR_TYPECTOR_REP_C_POINTER);
 MR_define_type_ctor_info(builtin, pred, 0, MR_TYPECTOR_REP_PRED);
 MR_define_type_ctor_info(builtin, func, 0, MR_TYPECTOR_REP_PRED);
+MR_define_type_ctor_info(builtin, tuple, 0, MR_TYPECTOR_REP_TUPLE);
 MR_define_type_ctor_info(array, array, 1, MR_TYPECTOR_REP_ARRAY);
 MR_define_type_ctor_info(std_util, univ, 0, MR_TYPECTOR_REP_UNIV);
 MR_define_type_ctor_info(std_util, type_desc, 0, MR_TYPECTOR_REP_TYPEINFO);
@@ -199,19 +202,29 @@
 {
 	MR_TypeInfo		type_info;
 	MR_TypeCtorInfo		type_ctor_info;
+	MR_TypeCtorRep		type_ctor_rep;
 	int			arity;
 	MR_TypeInfoParams	params;
 	MR_Type_Info		*args;
 
 	type_info = (MR_TypeInfo) ti;
 	type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
-	if (type_ctor_info->type_ctor_rep == MR_TYPECTOR_REP_PRED) {
-		arity = MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info);
-		params = MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(type_info);
-	} else {
-		arity = type_ctor_info->arity;
-		params = MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info);
+
+	/*
+	** Tuple and higher-order types do not have a fixed arity,
+	** so they need to be special cased here.
+	*/
+	type_ctor_rep = type_ctor_info->type_ctor_rep;
+	if (type_ctor_rep == MR_TYPECTOR_REP_TUPLE) {
+		return mercury__builtin____Unify____tuple_0_0(ti,
+			(MR_Tuple) x, (MR_Tuple) y);
+	} else if (type_ctor_rep == MR_TYPECTOR_REP_PRED) {
+		return mercury__builtin____Unify____pred_0_0((MR_Pred) x,
+			(MR_Pred) y);
 	}
+
+	arity = type_ctor_info->arity;
+	params = MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info);
 	args = (MR_Type_Info *) params;
 
 	switch(arity) {
@@ -247,19 +260,31 @@
 {
 	MR_TypeInfo		type_info;
 	MR_TypeCtorInfo		type_ctor_info;
+	MR_TypeCtorRep		type_ctor_rep;
 	int			arity;
 	MR_TypeInfoParams	params;
 	MR_Type_Info		*args;
 
 	type_info = (MR_TypeInfo) ti;
 	type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
-	if (type_ctor_info->type_ctor_rep == MR_TYPECTOR_REP_PRED) {
-		arity = MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info);
-		params = MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(type_info);
-	} else {
-		arity = type_ctor_info->arity;
-		params = MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info);
+
+	/*
+	** Tuple and higher-order types do not have a fixed arity,
+	** so they need to be special cased here.
+	*/
+	type_ctor_rep = type_ctor_info->type_ctor_rep;
+	if (type_ctor_rep == MR_TYPECTOR_REP_TUPLE) {
+		mercury__builtin____Compare____tuple_0_0(ti,
+			res, (MR_Tuple) x, (MR_Tuple) y);
+		return;
+	} else if (type_ctor_rep == MR_TYPECTOR_REP_PRED) {
+		mercury__builtin____Compare____pred_0_0(res,
+			(MR_Pred) x, (MR_Pred) y);
+	    	return;
 	}
+
+	arity = type_ctor_info->arity;
+	params = MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info);
 	args = (MR_Type_Info *) params;
 
 	switch(arity) {
@@ -384,6 +409,30 @@
 }
 
 bool
+mercury__builtin____Unify____tuple_0_0(MR_Type_Info ti, MR_Tuple x, MR_Tuple y)
+{
+	int i, arity;
+	bool result;
+	MR_TypeInfo type_info;
+	MR_TypeInfo arg_type_info;
+
+	type_info = (MR_TypeInfo) ti;
+	arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+
+	for (i = 0; i < arity; i++) {
+		/* type_infos are counted starting at one. */
+		arg_type_info =
+			MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info)[i + 1];
+		result = mercury__builtin__unify_2_p_0(
+				(MR_Type_Info) arg_type_info, x[i], y[i]);
+		if (result == FALSE) {
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+bool
 mercury__array____Unify____array_1_0(MR_Type_Info type_info,
 	MR_Array x, MR_Array y)
 {
@@ -509,6 +558,30 @@
 }
 
 void
+mercury__builtin____Compare____tuple_0_0(MR_Type_Info ti,
+	MR_Comparison_Result *result, MR_Tuple x, MR_Tuple y)
+{
+	int i, arity;
+	MR_TypeInfo type_info;
+	MR_TypeInfo arg_type_info;
+
+	type_info = (MR_TypeInfo) ti;
+	arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+
+	for (i = 0; i < arity; i++) {
+		/* type_infos are counted starting at one. */
+		arg_type_info =
+			MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info)[i + 1];
+		mercury__builtin__compare_3_p_0((MR_Type_Info) arg_type_info,
+				result, x[i], y[i]);
+		if (*result != MR_COMPARE_EQUAL) {
+			return;
+		}
+	}
+	*result = MR_COMPARE_EQUAL;
+}
+
+void
 mercury__array____Compare____array_1_0(
 	MR_Type_Info type_info, MR_Comparison_Result *result,
 	MR_Array x, MR_Array y)
@@ -621,6 +694,14 @@
 }
 
 static bool
+mercury__builtin__do_unify__tuple_0_0(MR_Type_Info type_info,
+		MR_Box x, MR_Box y)
+{
+	return mercury__builtin____Unify____tuple_0_0(
+		type_info, (MR_Tuple) x, (MR_Tuple) y);
+}
+
+static bool
 mercury__array__do_unify__array_1_0(MR_Type_Info type_info, MR_Box x, MR_Box y)
 {
 	return mercury__array____Unify____array_1_0(
@@ -739,6 +820,15 @@
 	MR_Box x, MR_Box y)
 {
 	MR_fatal_error("called compare/3 for pred type");
+}
+
+static void
+mercury__builtin__do_compare__tuple_0_0(
+	MR_Type_Info type_info, MR_Comparison_Result *result,
+	MR_Box x, MR_Box y)
+{
+	mercury__builtin____Compare____tuple_0_0(
+		type_info, result, (MR_Tuple) x, (MR_Tuple) y);
 }
 
 static void
Index: runtime/mercury.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury.h,v
retrieving revision 1.14
diff -u -u -r1.14 mercury.h
--- runtime/mercury.h	2000/07/20 10:39:36	1.14
+++ runtime/mercury.h	2000/07/22 23:54:19
@@ -123,6 +123,11 @@
 #endif
 
 /*
+** Tuples are always just arrays of polymorphic terms.
+*/
+typedef MR_Box *MR_Tuple;
+
+/*
 ** Typedefs used for the types of RTTI data structures.
 ** Many of these types are defined in mercury_type_info.h,
 ** but the ones which are used only by the MLDS back-end
@@ -140,12 +145,13 @@
 
 /*
 ** XXX Currently we hard-code the declarations of the first
-** five of these type-info struct types; this imposes a fixed
+** ten of these type-info struct types; this imposes a fixed
 ** limit of 10 on the arity of types.  (If this is exceeded,
 ** you'll get a parse error in the generated C code, due to
 ** an undeclared type.)
 ** Note that the code for compare and unify in runtime/mercury.c
-** also has a fixed limit of 5 on the arity of types.
+** also has a fixed limit of 5 on the arity of types (other than
+** higher-order and tuple types, which have no limit).
 ** Fortunately types with a high arity tend not to be used very
 ** often, so this is probably OK for now...
 */
@@ -209,6 +215,7 @@
 	mercury__builtin__builtin__type_ctor_info_c_pointer_0,
 	mercury__builtin__builtin__type_ctor_info_pred_0,
 	mercury__builtin__builtin__type_ctor_info_func_0,
+	mercury__builtin__builtin__type_ctor_info_tuple_0,
 	mercury__array__array__type_ctor_info_array_1,
 	mercury__std_util__std_util__type_ctor_info_univ_0,
 	mercury__std_util__std_util__type_ctor_info_type_desc_0,
@@ -233,6 +240,8 @@
 	mercury__builtin__builtin__type_ctor_info_character_0
 #define mercury__builtin____type_ctor_info_pred_0 \
 	mercury__builtin__builtin__type_ctor_info_pred_0
+#define mercury__builtin____type_ctor_info_tuple_0 \
+	mercury__builtin__builtin__type_ctor_info_tuple_0
 
 /*
 ** The compiler generates references to this constant.
@@ -369,6 +378,8 @@
 	MR_C_Pointer x, MR_C_Pointer y); 
 bool mercury__builtin____Unify____func_0_0(MR_Func x, MR_Func y); 
 bool mercury__builtin____Unify____pred_0_0(MR_Pred x, MR_Pred y); 
+bool mercury__builtin____Unify____tuple_0_0(MR_Type_Info type_info,
+	MR_Tuple x, MR_Tuple y); 
 bool mercury__array____Unify____array_1_0(MR_Type_Info type_info,
 	MR_Array x, MR_Array y);
 bool mercury__std_util____Unify____univ_0_0(MR_Univ x, MR_Univ y); 
@@ -400,6 +411,8 @@
 	MR_Comparison_Result *result, MR_Func x, MR_Func y);
 void mercury__builtin____Compare____pred_0_0(
 	MR_Comparison_Result *result, MR_Pred x, MR_Pred y); 
+void mercury__builtin____Compare____tuple_0_0(MR_Type_Info type_info,
+	MR_Comparison_Result *result, MR_Tuple x, MR_Tuple y); 
 void mercury__array____Compare____array_1_0(MR_Type_Info type_info,
 	MR_Comparison_Result *result, MR_Array x, MR_Array y);
 void mercury__std_util____Compare____univ_0_0(
Index: runtime/mercury_deep_copy_body.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_deep_copy_body.h,v
retrieving revision 1.23
diff -u -u -r1.23 mercury_deep_copy_body.h
--- runtime/mercury_deep_copy_body.h	2000/05/17 18:48:53	1.23
+++ runtime/mercury_deep_copy_body.h	2000/07/24 06:39:05
@@ -444,6 +444,40 @@
         }
         break;
 
+    case MR_TYPECTOR_REP_TUPLE:
+        {
+            Word    *data_value;
+            int     arity, i;
+
+            assert(MR_tag(data) == 0);
+            data_value = (Word *) MR_body(data, MR_mktag(0));
+
+            if (in_range(data_value)) {
+                Word *new_data_ptr;
+                MR_TypeInfo *arg_typeinfo_vector;
+
+                arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+
+                /* allocate space for the new tuple */
+                incr_saved_hp(new_data, arity);
+                new_data_ptr = (Word *) new_data;
+
+                arg_typeinfo_vector =
+                    MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info);
+                for (i = 0; i < arity; i++) {
+                   /* type_infos are counted from one */
+                   new_data_ptr[i] = copy(&data_value[i],
+                        (const MR_TypeInfo) arg_typeinfo_vector[i + 1],
+                        lower_limit, upper_limit);
+                }
+                leave_forwarding_pointer(data_ptr, new_data);
+            } else {
+                new_data = data;
+                found_forwarding_pointer(data);
+            }
+        }
+        break;
+
     case MR_TYPECTOR_REP_UNIV:
         {
             Word    *data_value;
@@ -644,21 +678,23 @@
             return (MR_TypeInfo) type_ctor_info;
         }
 
-        if (type_ctor_info->type_ctor_rep == MR_TYPECTOR_REP_PRED) {
+        if (MR_type_ctor_rep_is_variable_arity(
+                type_ctor_info->type_ctor_rep))
+        {
             arity = MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info);
             type_info_args =
                 MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(type_info);
             incr_saved_hp(LVALUE_CAST(Word, new_type_info_arena),
                 MR_higher_order_type_info_size(arity));
             MR_fill_in_higher_order_type_info(new_type_info_arena,
-		type_ctor_info, arity, new_type_info_args);
+                type_ctor_info, arity, new_type_info_args);
         } else {
             arity = type_ctor_info->arity;
             type_info_args = MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info);
             incr_saved_hp(LVALUE_CAST(Word, new_type_info_arena),
                 MR_first_order_type_info_size(arity));
             MR_fill_in_first_order_type_info(new_type_info_arena,
-		type_ctor_info, new_type_info_args);
+                type_ctor_info, new_type_info_args);
         }
         for (i = 1; i <= arity; i++) {
             new_type_info_args[i] = copy_type_info(&type_info_args[i],
Index: runtime/mercury_make_type_info_body.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_make_type_info_body.h,v
retrieving revision 1.4
diff -u -u -r1.4 mercury_make_type_info_body.h
--- runtime/mercury_make_type_info_body.h	2000/07/20 04:18:34	1.4
+++ runtime/mercury_make_type_info_body.h	2000/07/22 23:54:20
@@ -62,7 +62,8 @@
 		return MR_pseudo_type_info_is_ground(pseudo_type_info);
 	}
 
-	if (type_ctor_info->type_ctor_rep == MR_TYPECTOR_REP_PRED) {
+	if (MR_type_ctor_rep_is_variable_arity(type_ctor_info->type_ctor_rep))
+	{
 		arity = MR_PSEUDO_TYPEINFO_GET_HIGHER_ORDER_ARITY(
 			pseudo_type_info);
 		start_region_size = 2;
Index: runtime/mercury_tabling.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_tabling.c,v
retrieving revision 1.26
diff -u -u -r1.26 mercury_tabling.c
--- runtime/mercury_tabling.c	2000/05/08 14:07:28	1.26
+++ runtime/mercury_tabling.c	2000/07/24 06:37:55
@@ -575,7 +575,8 @@
 	** sense. This is OK, because in that case it will never be used.
 	*/
 
-	if (type_ctor_info->type_ctor_rep == MR_TYPECTOR_REP_PRED) {
+	if (MR_type_ctor_rep_is_variable_arity(type_ctor_info->type_ctor_rep))
+	{
 		arity = MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info);
 		arg_vector = MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(
 			type_info);
@@ -813,6 +814,25 @@
                 */
                 MR_DEBUG_TABLE_INT(table, data);
         #endif
+                break;
+            }
+
+        case MR_TYPECTOR_REP_TUPLE:
+           {
+                Word        *data_value;
+                MR_TypeInfo *arg_type_info_vector;
+                int         arity;
+                int         i;
+
+                data_value = (Word *) data;
+                arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+                arg_type_info_vector =
+                        MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info);
+                for (i = 0; i < arity; i++) {
+                    /* type_infos are counted starting at one */
+                    MR_DEBUG_TABLE_ANY(table, arg_type_info_vector[i + 1],
+                        data_value[i]);
+                }
                 break;
             }
 
Index: runtime/mercury_type_info.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_type_info.c,v
retrieving revision 1.38
diff -u -u -r1.38 mercury_type_info.c
--- runtime/mercury_type_info.c	2000/05/08 16:11:06	1.38
+++ runtime/mercury_type_info.c	2000/07/22 23:54:20
@@ -183,11 +183,12 @@
 	** If the type_ctor_info addresses are equal, we don't need to
 	** compare the arity of the types - they must be the same -
 	** unless they are higher-order (which are all mapped to
-	** pred/0). 
+	** pred/0) or tuples (which are all mapped to tuple/0). 
 	** But we need to recursively compare the argument types, if any.
 	*/
-		/* Check for higher order */
-	if (type_ctor_info_1->type_ctor_rep == MR_TYPECTOR_REP_PRED) 
+		/* Check for higher order or tuples */
+	if (MR_type_ctor_rep_is_variable_arity(
+			type_ctor_info_1->type_ctor_rep))
 	{
 		int	num_arg_types_2;
 
Index: runtime/mercury_type_info.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.52
diff -u -u -r1.52 mercury_type_info.h
--- runtime/mercury_type_info.h	2000/07/12 13:54:40	1.52
+++ runtime/mercury_type_info.h	2000/07/28 05:42:00
@@ -91,11 +91,12 @@
 /*
 ** The C structures of typeinfos and pseudotypeinfos are sort of lies,
 ** for two reasons. First, we want one C type that can describe both first
-** order and higher order (pseudo-) typeinfos, and they have different
-** structures (higher order (pseudo-) typeinfos have an extra word, the arity,
-** between the type_ctor_info and the argument (pseudo-) typeinfos). Second,
-** we can't rely on the C compiler having a mechanism for the declaration
-** of dynamically sized vectors embedded in structures.
+** order, and higher order and tuple (pseudo-) typeinfos, and they have
+** different structures (higher order and tuple (pseudo-) typeinfos have
+** an extra word, the arity, between the type_ctor_info and the argument
+** (pseudo-) typeinfos). Second, we can't rely on the C compiler having a
+** mechanism for the declaration of dynamically sized vectors embedded in
+** structures.
 **
 ** Instead, the types MR_TypeInfo and MR_PseudoTypeInfo are designed as
 ** error-detection devices. Values of these types should be manipulated
@@ -132,17 +133,22 @@
 	MR_TypeCtorInfo     MR_ti_type_ctor_info;			\
 	MR_TypeInfo         MR_ti_first_order_arg_typeinfos[ARITY];	\
     }
+
+/* Tuple types also use the higher-order type-info structure. */
 #define MR_HIGHER_ORDER_TYPEINFO_STRUCT(NAME, ARITY)			\
     struct NAME {							\
 	MR_TypeCtorInfo     MR_ti_type_ctor_info;			\
 	Integer             MR_ti_higher_order_arity;			\
 	MR_TypeInfo         MR_ti_higher_order_arg_typeinfos[ARITY];	\
     }
+
 #define MR_FIRST_ORDER_PSEUDOTYPEINFO_STRUCT(NAME, ARITY)		\
     struct NAME {							\
 	MR_TypeCtorInfo     MR_pti_type_ctor_info;			\
 	MR_PseudoTypeInfo   MR_pti_first_order_arg_pseudo_typeinfos[ARITY]; \
     }
+
+/* Tuple types also use the higher-order pseude-type-info structure. */
 #define MR_HIGHER_ORDER_PSEUDOTYPEINFO_STRUCT(NAME, ARITY)		\
     struct NAME {							\
 	MR_TypeCtorInfo     MR_pti_type_ctor_info;			\
@@ -223,15 +229,24 @@
 #define MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info)               \
     ((type_info)->MR_ti_higher_order_arity)
 
+#define MR_TYPEINFO_GET_TUPLE_ARITY(type_info)                      \
+    MR_TYPEINFO_GET_HIGHER_ORDER_ARITY(type_info)
+
 #define MR_PSEUDO_TYPEINFO_GET_HIGHER_ORDER_ARITY(pseudo_type_info) \
     ((pseudo_type_info)->MR_pti_higher_order_arity)
 
+#define MR_PSEUDO_TYPEINFO_GET_TUPLE_ARITY(pseudo_type_info)        \
+    MR_PSEUDO_TYPEINFO_GET_HIGHER_ORDER_ARITY(pseudo_type_info)
+
+#define MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info)           \
+    ((MR_TypeInfoParams) &(type_info)->MR_ti_type_ctor_info)
+
 #define MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(type_info)          \
     ((MR_TypeInfoParams)                                            \
         &(type_info)->MR_ti_higher_order_arity)
 
-#define MR_TYPEINFO_GET_FIRST_ORDER_ARG_VECTOR(type_info)           \
-    ((MR_TypeInfoParams) &(type_info)->MR_ti_type_ctor_info)
+#define MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(type_info)                 \
+    MR_TYPEINFO_GET_HIGHER_ORDER_ARG_VECTOR(type_info)
 
 /*
 ** Macros for creating type_infos.
@@ -243,6 +258,9 @@
 #define MR_higher_order_type_info_size(arity)                       \
     (2 + (arity))
 
+#define MR_tuple_type_info_size(arity)                              \
+    MR_higher_order_type_info_size(arity)
+
 #define MR_fill_in_first_order_type_info(arena, type_ctor_info, vector) \
     do {                                                            \
         MR_TypeInfo new_ti;                                         \
@@ -260,6 +278,9 @@
         (vector) = (MR_TypeInfoParams) &new_ti->MR_ti_higher_order_arity;\
     } while (0)
 
+#define MR_fill_in_tuple_type_info(arena, type_ctor_info, arity, vector) \
+    MR_fill_in_higher_order_type_info(arena, type_ctor_info, arity, vector)
+
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -397,6 +418,7 @@
     MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_FLOAT),
     MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_STRING),
     MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_PRED),
+    MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_TUPLE),
     MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_UNIV),
     MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_VOID),
     MR_DEFINE_ENUM_CONST(MR_TYPECTOR_REP_C_POINTER),
@@ -441,6 +463,7 @@
     "FLOAT",                                    \
     "STRING",                                   \
     "PRED",                                     \
+    "TUPLE",                                    \
     "UNIV",                                     \
     "VOID",                                     \
     "C_POINTER",                                \
@@ -470,6 +493,16 @@
     || ((rep) == MR_TYPECTOR_REP_NOTAG_GROUND)              \
     || ((rep) == MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ))
 
+/*
+** Returns TRUE if the type_ctor_info is used to represent
+** multiple types of different arities. The arity is stored
+** as the first element of the argument type-info vector.
+** This is true for higher-order types and tuple types.
+*/
+#define MR_type_ctor_rep_is_variable_arity(rep)             \
+    (  ((rep) == MR_TYPECTOR_REP_PRED)                      \
+    || ((rep) == MR_TYPECTOR_REP_TUPLE))
+
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -937,18 +970,24 @@
 #ifdef MR_HIGHLEVEL_CODE
   extern const struct MR_TypeCtorInfo_Struct 
         mercury__builtin__builtin__type_ctor_info_pred_0,
-        mercury__builtin__builtin__type_ctor_info_func_0;
+        mercury__builtin__builtin__type_ctor_info_func_0,
+        mercury__builtin__builtin__type_ctor_info_tuple_0;
   #define MR_TYPE_CTOR_INFO_HO_PRED                                     \
         (&mercury__builtin__builtin__type_ctor_info_pred_0)
   #define MR_TYPE_CTOR_INFO_HO_FUNC                                     \
         (&mercury__builtin__builtin__type_ctor_info_func_0)
+  #define MR_TYPE_CTOR_INFO_TUPLE                                       \
+        (&mercury__builtin__builtin__type_ctor_info_tuple_0)
 #else
   MR_DECLARE_TYPE_CTOR_INFO_STRUCT(mercury_data___type_ctor_info_pred_0);
   MR_DECLARE_TYPE_CTOR_INFO_STRUCT(mercury_data___type_ctor_info_func_0);
+  MR_DECLARE_TYPE_CTOR_INFO_STRUCT(mercury_data___type_ctor_info_tuple_0);
   #define MR_TYPE_CTOR_INFO_HO_PRED                                     \
         ((MR_TypeCtorInfo) &mercury_data___type_ctor_info_pred_0)
   #define MR_TYPE_CTOR_INFO_HO_FUNC                                     \
         ((MR_TypeCtorInfo) &mercury_data___type_ctor_info_func_0)
+  #define MR_TYPE_CTOR_INFO_TUPLE                                       \
+        ((MR_TypeCtorInfo) &mercury_data___type_ctor_info_tuple_0)
 #endif
 
 #define MR_TYPE_CTOR_INFO_IS_HO_PRED(T)                                 \
@@ -957,6 +996,8 @@
         (T == MR_TYPE_CTOR_INFO_HO_FUNC)
 #define MR_TYPE_CTOR_INFO_IS_HO(T)                                      \
         (MR_TYPE_CTOR_INFO_IS_HO_FUNC(T) || MR_TYPE_CTOR_INFO_IS_HO_PRED(T))
+#define MR_TYPE_CTOR_INFO_IS_TUPLE(T)                                   \
+        (T == MR_TYPE_CTOR_INFO_TUPLE)
 
 /*---------------------------------------------------------------------------*/
 
Index: runtime/mercury_unify_compare_body.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_unify_compare_body.h,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_unify_compare_body.h
--- runtime/mercury_unify_compare_body.h	2000/04/05 06:29:00	1.2
+++ runtime/mercury_unify_compare_body.h	2000/07/24 06:36:38
@@ -359,6 +359,42 @@
 
             tailcall_user_pred();
 
+        case MR_TYPECTOR_REP_TUPLE:
+            {
+                int     i;
+                int     type_arity;
+                int     result;
+
+                type_arity = MR_TYPEINFO_GET_TUPLE_ARITY(type_info);
+
+                for (i = 0; i < type_arity; i++) {
+                    MR_TypeInfo arg_type_info;
+
+                    /* type_infos are counted from one */
+                    arg_type_info = MR_TYPEINFO_GET_TUPLE_ARG_VECTOR(
+                                            type_info)[i + 1];
+
+#ifdef  select_compare_code
+                    result = MR_generic_compare(arg_type_info,
+                                ((Word *) x)[i], ((Word *) y)[i]);
+                    if (result != MR_COMPARE_EQUAL) {
+                        return_answer(result);
+                    }
+#else
+                    result = MR_generic_unify(arg_type_info,
+                                ((Word *) x)[i], ((Word *) y)[i]);
+                    if (! result) {
+                        return_answer(FALSE);
+                    }
+#endif
+                }
+#ifdef  select_compare_code
+                return_answer(MR_COMPARE_EQUAL);
+#else
+                return_answer(TRUE);
+#endif
+            }
+
         case MR_TYPECTOR_REP_ENUM:
         case MR_TYPECTOR_REP_INT:
         case MR_TYPECTOR_REP_CHAR:
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.87
diff -u -u -r1.87 Mmakefile
--- tests/hard_coded/Mmakefile	2000/06/05 02:47:36	1.87
+++ tests/hard_coded/Mmakefile	2000/07/26 05:08:06
@@ -107,6 +107,7 @@
 	term_io_test \
 	type_to_term_bug \
 	tim_qual1 \
+	tuple_test \
 	user_defined_equality \
 	write \
 	write_reg1
Index: tests/hard_coded/construct.exp
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/construct.exp,v
retrieving revision 1.4
diff -u -u -r1.4 construct.exp
--- tests/hard_coded/construct.exp	2000/03/10 13:38:19	1.4
+++ tests/hard_coded/construct.exp	2000/07/31 05:25:24
@@ -158,6 +158,10 @@
 -1 functors in this type
 
 
+1 functors in this type
+0 - {}/4
+
+
 
 TESTING OTHER TYPES
 1 functors in this type
@@ -220,3 +224,7 @@
 Constructed: poly_two("goodbye")
 About to construct poly_four/2
 Constructed: poly_four(1, "goodbye")
+About to construct {}/3
+Constructed: {4, "five", '6'}
+About to call construct_tuple
+Constructed tuple: univ({[1, 2, 3], [one, two, three], 1, 2.10000000000000} : {list:list(int), list:list(construct:enum), int, float)})
Index: tests/hard_coded/construct.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/construct.m,v
retrieving revision 1.3
diff -u -u -r1.3 construct.m
--- tests/hard_coded/construct.m	2000/03/24 10:28:00	1.3
+++ tests/hard_coded/construct.m	2000/07/31 03:46:38
@@ -93,9 +93,16 @@
 	test_construct_2(type_of(poly_four(3, "hello")), "poly_one", 1, [One]),
 	test_construct_2(type_of(poly_four(3, "hello")), "poly_two", 1, [Bye]),
 	test_construct_2(type_of(poly_four(3, "hello")), "poly_four", 2, 
-		[One, Bye]).
+		[One, Bye]),
+	test_construct_2(type_of({1, "two", '3'}), "{}", 3,
+		[univ(4), univ("five"), univ('6')]),
+
+	io__write_string("About to call construct_tuple\n"),
+	{ Tuple = construct_tuple([NumList, EnumList, One, TwoPointOne]) },
+	io__write_string("Constructed tuple: "),
+	io__write(Tuple),
+	io__nl.
 
-	
 :- pred test_construct_2(type_desc::in, string::in, int::in, list(univ)::in,
 	io__state::di, io__state::uo) is det.
 test_construct_2(TypeInfo, FunctorName, Arity, Args) -->
@@ -247,6 +254,9 @@
 	
 		% test predicates	
 	test_all(newline), newline,
+
+		% test tuples
+	test_all({1, "a", 'a', {4, 'd'}}), newline,
 
 	newline.
 
Index: tests/hard_coded/deep_copy.exp
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/deep_copy.exp,v
retrieving revision 1.2
diff -u -u -r1.2 deep_copy.exp
--- tests/hard_coded/deep_copy.exp	2000/03/10 13:38:19	1.2
+++ tests/hard_coded/deep_copy.exp	2000/07/31 03:50:39
@@ -90,6 +90,9 @@
 univ(["hi! I\'m a univ!"] : list:list(string))
 univ(["hi! I\'m a univ!"] : list:list(string))
 univ(["hi! I\'m a univ!"] : list:list(string))
+{1, "two", '3', {4, '5', "6"}}
+{1, "two", '3', {4, '5', "6"}}
+{1, "two", '3', {4, '5', "6"}}
 
 TESTING OTHER TYPES
 var(1)
Index: tests/hard_coded/deep_copy.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/deep_copy.m,v
retrieving revision 1.2
diff -u -u -r1.2 deep_copy.m
--- tests/hard_coded/deep_copy.m	2000/03/10 13:38:20	1.2
+++ tests/hard_coded/deep_copy.m	2000/07/31 02:20:05
@@ -207,6 +207,9 @@
 		% XXX we don't deep copy predicates correctly yet
 	%test_all(newline),
 
+		% test tuples
+	test_all({1, "two", '3', {4, '5', "6"}}),
+
 	newline.
 
 	% Note: testing abstract types is always going to have results
Index: tests/hard_coded/expand.exp
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/expand.exp,v
retrieving revision 1.3
diff -u -u -r1.3 expand.exp
--- tests/hard_coded/expand.exp	1998/12/04 01:11:12	1.3
+++ tests/hard_coded/expand.exp	2000/07/25 11:12:26
@@ -109,6 +109,10 @@
 no arguments
 expand: functor <<predicate>> arity 0 arguments []
 
+{}/4
+argument 4 of functor {} was:{1, 2, 3, 4}
+expand: functor {} arity 4 arguments [1, 'b', "third", {1, 2, 3, 4}]
+
 
 TESTING OTHER TYPES
 var/1
Index: tests/hard_coded/expand.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/expand.m,v
retrieving revision 1.5
diff -u -u -r1.5 expand.m
--- tests/hard_coded/expand.m	1997/06/04 09:59:57	1.5
+++ tests/hard_coded/expand.m	2000/07/24 23:11:54
@@ -142,6 +142,9 @@
 		% test predicates	
 	test_all(newline), newline,
 
+		% test tuples
+	test_all({1, 'b', "third", {1,2,3,4}}), newline,
+
 	newline.
 
 	% Note: testing abstract types is always going to have results
Index: tests/hard_coded/tuple_test.exp
===================================================================
RCS file: tuple_test.exp
diff -N tuple_test.exp
--- /dev/null	Tue Aug  1 14:05:00 2000
+++ tuple_test.exp	Mon Jul 31 15:26:00 2000
@@ -0,0 +1,20 @@
+testing io__write:
+{'a', {'b', 1, [1, 2, 3], {}, { 1 }}, "string"}
+{'a', {'b', 1, [1, 2, 3], {}, { 1 }}, "string"}
+testing type_to_term:
+{a, {b, 1, [1, 2, 3], {}, { 1 }}, "string"}
+testing term_to_type:
+term_to_type succeeded
+{'a', {'b', 1, [1, 2, 3], {}, { 1 }}, "string"}
+testing unification:
+unify test 1 succeeded
+unify test 2 succeeded
+testing comparison:
+comparison test 1 succeeded
+comparison test 2 succeeded
+testing tuple switches:
+[1, 2]
+4
+testing complicated unification
+complicated unification test 1 succeeded
+complicated unification test 2 succeeded
Index: tests/hard_coded/tuple_test.m
===================================================================
RCS file: tuple_test.m
diff -N tuple_test.m
--- /dev/null	Tue Aug  1 14:05:00 2000
+++ tuple_test.m	Mon Jul 31 14:20:20 2000
@@ -0,0 +1,123 @@
+:- module tuple_test.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module bool, list, char, string, int.
+:- import_module term, std_util, term_io, varset.
+
+main -->
+	io__write_string("testing io__write:\n"),
+	{ Tuple = {'a', {'b', 1, [1,2,3], {}, {1}}, "string"} },
+	io__write(Tuple),
+	io__nl,
+	io__write({}('a', {'b', 1, [1,2,3], {}, {1}}, "string")),
+	io__nl,
+	
+	io__write_string("testing type_to_term:\n"),
+	{ type_to_term(Tuple, TupleTerm) },
+	{ is_generic_term(TupleTerm) },
+	{ varset__init(VarSet) },
+	term_io__write_term(VarSet, TupleTerm),
+	io__nl,
+
+	io__write_string("testing term_to_type:\n"),
+	(
+		{ has_type(NewTuple, type_of(Tuple)) },
+		{ term_to_type(TupleTerm, NewTuple) }
+	->
+		io__write_string("term_to_type succeeded\n"),
+		io__write(NewTuple),
+		io__nl
+	;
+		io__write_string("term_to_type failed\n")
+	),
+
+	% Test in-in unification of tuples.
+	io__write_string("testing unification:\n"),
+	( { unify_tuple({1, 'a', 1, "string"}, {1, 'a', 1, "string"}) } ->
+		io__write_string("unify test 1 succeeded\n")
+	;
+		io__write_string("unify test 1 failed\n")
+	),
+ 	( { unify_tuple({2, 'b', 1, "foo"}, {2, 'b', 1, "bar"}) } ->
+		io__write_string("unify test 2 failed\n")
+	;
+		io__write_string("unify test 2 succeeded\n")
+	),
+
+	% Test comparison of tuples.
+	io__write_string("testing comparison:\n"),
+	{ compare(Res1, {1, 'a', 1, "string"}, {1, 'a', 1, "string"}) },
+	( { Res1 = (=) } ->
+		io__write_string("comparison test 1 succeeded\n")
+	;
+		io__write_string("comparison test 1 failed\n")
+	),		
+
+	{ compare(Res2, {2, 'b', 1, "foo"}, {2, 'b', 1, "bar"}) },
+	( { Res2 = (>) } ->
+		io__write_string("comparison test 2 succeeded\n")
+	;
+		io__write_string("comparison test 2 failed\n")
+	),
+
+	io__write_string("testing tuple switches:\n"),
+	{ solutions(tuple_switch_test({1, 2}), Solns1) },
+	io__write(Solns1),
+	io__nl,
+
+	{ tuple_switch_test_2({no, 3, 4}, Int) },
+	io__write_int(Int),
+	io__nl,
+
+	%
+	% These tests should generate an out-of-line unification
+	% predicate for the unification with the output argument.
+	%
+	io__write_string("testing complicated unification\n"),
+	( { choose(yes, {1, "b", 'c'}, {4, "e", 'f'}, {1, _, _}) } ->
+		io__write_string("complicated unification test 1 succeeded\n")
+	;
+		io__write_string("complicated unification test 1 failed\n")
+	),
+	( { choose(yes, {5, "b", 'c'}, {9, "e", 'f'}, {1, _, _}) } ->
+		io__write_string("complicated unification test 2 failed\n")
+	;
+		io__write_string("complicated unification test 2 succeeded\n")
+	).
+
+:- pred is_generic_term(term::unused).
+
+is_generic_term(_).
+
+:- type foo(A, B, C) == {int, A, B, C}.
+
+:- pred unify_tuple(foo(A, B, C)::in,
+	{int, A, B, C}::in(bound({ground, ground, ground, ground}))) is semidet.
+:- pragma no_inline(unify_tuple/2).
+
+unify_tuple(X, X).
+
+:- pred choose(bool::in, T::in, T::in, T::out) is det.
+:- pragma no_inline(choose/4).
+
+choose(yes, A, _, A).
+choose(no, _, B, B).
+
+:- pred tuple_switch_test({int, int}::in, int::out) is multi.
+:- pragma no_inline(tuple_switch_test/2).
+
+tuple_switch_test({A, _}, A).
+tuple_switch_test({_, B}, B).
+
+:- pred tuple_switch_test_2({bool, int, int}::in, int::out) is det.
+:- pragma no_inline(tuple_switch_test_2/2).
+
+tuple_switch_test_2({yes, A, _}, A).
+tuple_switch_test_2({no, _, B}, B).
Index: tests/hard_coded/write.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/write.m,v
retrieving revision 1.5
diff -u -u -r1.5 write.m
--- tests/hard_coded/write.m	1998/11/09 02:44:03	1.5
+++ tests/hard_coded/write.m	2000/08/01 04:11:41
@@ -58,10 +58,10 @@
 
 test_ops -->
 	io__write(var("X") + int(3) * var("X^2") ; (type)), newline,
-	io__write({type}), newline,
-	io__write({:-}), newline,
+	io__write(write:{type}), newline,
+	io__write(write:{:-}), newline,
 	io__write((:-)), newline,
-	io__write({blah}), newline,
+	io__write(write:{blah}), newline,
 	io__write((blah ; (type), (type) * blah ; (type))), newline,
 	io__write(((blah ; blah), blah) * blah ; blah), newline,
 	io__write((type) * blah ; (type)), newline.
Index: tests/hard_coded/typeclasses/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/Mmakefile,v
retrieving revision 1.30
diff -u -u -r1.30 Mmakefile
--- tests/hard_coded/typeclasses/Mmakefile	2000/07/06 06:25:24	1.30
+++ tests/hard_coded/typeclasses/Mmakefile	2000/07/31 04:22:37
@@ -38,6 +38,7 @@
 	record_syntax \
 	superclass_call \
 	test_default_func_mode \
+	tuple_instance \
 	typeclass_exist_method \
 	typeclass_test_5 \
 	typeclass_test_6 \
Index: tests/hard_coded/typeclasses/tuple_instance.exp
===================================================================
RCS file: tuple_instance.exp
diff -N tuple_instance.exp
--- /dev/null	Tue Aug  1 14:05:00 2000
+++ tuple_instance.exp	Mon Jul 31 15:27:57 2000
@@ -0,0 +1 @@
+9
Index: tests/hard_coded/typeclasses/tuple_instance.m
===================================================================
RCS file: tuple_instance.m
diff -N tuple_instance.m
--- /dev/null	Tue Aug  1 14:05:00 2000
+++ tuple_instance.m	Wed Jul 26 15:08:40 2000
@@ -0,0 +1,32 @@
+:- module tuple_instance.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module int, string.
+
+main -->
+	{ Size = size({"ok", "failed"}) },
+	io__write_int(Size),
+	io__nl.
+
+:- typeclass size(T) where [
+	func size(T) = int
+].
+
+:- instance size({T, U}) <= (size(T), size(U)) where [
+	func(size/1) is tuple_size
+].
+
+:- instance size(string) where [
+	func(size/1) is string__length
+].
+
+:- func tuple_size({T, U}) = int <= (size(T), size(U)).
+
+tuple_size({T, U}) = 1 + size(T) + size(U).
Index: tests/invalid/errors2.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/errors2.err_exp,v
retrieving revision 1.9
diff -u -u -r1.9 errors2.err_exp
--- tests/invalid/errors2.err_exp	1999/11/09 22:40:12	1.9
+++ tests/invalid/errors2.err_exp	2000/07/28 00:53:38
@@ -54,6 +54,11 @@
 errors2.m:078:   error: undefined symbol `[]/0'.
 errors2.m:078: In clause for predicate `errors2:type_error_8/0':
 errors2.m:078:   error: undefined predicate `from_char_list/2'.
+errors2.m:085: In clause for predicate `errors2:type_error_9/0':
+errors2.m:085:   type error in unification of variable `X'
+errors2.m:085:   and variable `Y'.
+errors2.m:085:   `X' has type `{int, string, character}',
+errors2.m:085:   `Y' has type `{string, character, int}'.
 errors2.m:009: Inferred :- pred bind_type_param(int).
 errors2.m:019: In clause for `unresolved_polymorphism':
 errors2.m:019:   in argument 1 of call to predicate `errors2:bind_type_param/2':
Index: tests/invalid/errors2.err_exp2
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/errors2.err_exp2,v
retrieving revision 1.4
diff -u -u -r1.4 errors2.err_exp2
--- tests/invalid/errors2.err_exp2	1999/11/09 22:40:14	1.4
+++ tests/invalid/errors2.err_exp2	2000/07/28 00:52:14
@@ -54,5 +54,10 @@
 errors2.m:078:   error: undefined symbol `[]/0'.
 errors2.m:078: In clause for predicate `errors2:type_error_8/0':
 errors2.m:078:   error: undefined predicate `from_char_list/2'.
+errors2.m:085: In clause for predicate `errors2:type_error_9/0':
+errors2.m:085:   type error in unification of variable `X'
+errors2.m:085:   and variable `Y'.
+errors2.m:085:   `X' has type `{int, string, character}',
+errors2.m:085:   `Y' has type `{string, character, int}'.
 errors2.m:009: Inferred :- pred bind_type_param(int).
 For more information, try recompiling with `-E'.
Index: tests/invalid/errors2.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/errors2.m,v
retrieving revision 1.4
diff -u -u -r1.4 errors2.m
--- tests/invalid/errors2.m	1997/06/29 23:24:38	1.4
+++ tests/invalid/errors2.m	2000/07/28 00:51:55
@@ -78,4 +78,10 @@
 	from_char_list([], Str),
 	string__from_char_list(list:[], Str).
 
+:- pred type_error_9.
+type_error_9 :-
+	X = {1, "2", '3'},
+	Y = {"1", '2', 3},
+	X = Y.
+
 %-----------------------------------------------------------------------------%
Index: tests/tabling/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/tabling/Mmakefile,v
retrieving revision 1.12
diff -u -u -r1.12 Mmakefile
--- tests/tabling/Mmakefile	2000/04/05 06:11:35	1.12
+++ tests/tabling/Mmakefile	2000/07/25 12:10:51
@@ -12,6 +12,7 @@
 	expand \
 	expand_float \
 	expand_poly \
+	expand_tuple \
 	fib \
 	fib_float \
 	fib_list \
Index: util/mdemangle.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mdemangle.c,v
retrieving revision 1.36
diff -u -u -r1.36 mdemangle.c
--- util/mdemangle.c	1999/09/30 21:33:14	1.36
+++ util/mdemangle.c	2000/07/26 04:59:25
@@ -908,7 +908,8 @@
 		{ "f_slash", "/" },
 		{ "f_comma", "," },
 		{ "f_semicolon", ";" },
-		{ "f_cut", "!" }
+		{ "f_cut", "!" },
+		{ "f_tuple", "{}" }
 	};
 	const int num_translations =
 		sizeof(translations) / sizeof(translations[0]);
Index: w3/news/newsdb.inc
===================================================================
RCS file: /home/mercury1/repository/w3/news/newsdb.inc,v
retrieving revision 1.47
diff -u -u -r1.47 newsdb.inc
--- w3/news/newsdb.inc	2000/07/26 06:27:36	1.47
+++ w3/news/newsdb.inc	2000/07/31 05:39:50
@@ -21,6 +21,14 @@
 
 $newsdb = array(
 
+"1 August 2000" => array("Tuple types",
+
+"Mercury now has builtin tuple types, similar to those in
+most other functional languages. The latest
+<A HREF=\"download/rotd.html\">release of the day</A>
+contains tuple support."
+),
+
 "26 Jul 2000" => array("Mercury and Microsoft's .NET",
 
 "A page outlining the status of Mercury on Microsoft's net .NET
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list