[m-dev.] for review: improvements for record syntax

Simon Taylor stayl at cs.mu.OZ.AU
Tue Dec 5 13:02:57 AEDT 2000



Estimated hours taken: 5

Allow field access functions to take extra arguments.
Change the field update function names from `'field:='/2' to `'field :='/2'

compiler/make_hlds.m:
        Handle field names with arguments.

compiler/hlds_pred.m:
        Add " :=" as the suffix for a field update function,
        rather than ":=".

compiler/typecheck.m:
        Update instances of `field:='/2 in comments.

compiler/det_util.m:
compiler/simplify.m:
        `det_info_vartypes' was defined using the `field:=' syntax.
        Change it into a normal predicate for bootstrapping.

library/array.m:
library/map.m:
        Add field access functions `elem/2' and `'elem :='/3'.
        For maps, the `elem' function calls `map__search',
        so add field access functions `det_elem' and `det_elem :='
        to call `map__lookup' and `map__det_update'.

NEWS:
doc/reference_manual.tex:
        Document the changes.

        Improve readability by changing occurrences
        of `X^field' to `X ^ field'.

tests/hard_coded/typeclasses/record_syntax.{m,exp}:
        Test field names with arguments.

tests/invalid/record_syntax_errors.err_exp:
	Update the expected output.


Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.181
diff -u -u -r1.181 NEWS
--- NEWS	2000/12/04 05:43:31	1.181
+++ NEWS	2000/12/04 15:40:54
@@ -14,6 +14,11 @@
   See the "Explicit type quantification" and "Variable scoping"
   sections of the language reference manual for details.
 
+* We've added support for tuple types, similar to those in most
+  other functional languages. Tuples use the syntax `{A, B, ...}'.
+  See the "Builtin types" section of the "Types" chapter of the
+  Mercury Language Reference Manual for details.
+
 * We've added support for record syntax, so that fields of
   constructors can be conveniently extracted and updated
   without writing lots of trivial access predicates.
@@ -23,18 +28,18 @@
   Note that the syntax has changed slightly since the version
   that appeared in the release of the day in early January 2000.
   `Value =^ field' is now the syntax for DCG field selection,
-  rather than `Value := ^ field'.
+  rather than `Value := ^ field'. Field update functions are
+  named 'field :=' rather than 'field:='. We also allow
+  field access functions to take extra arguments.
+
+* The behaviour of the Mercury parser (parser__read_term) applied
+  to terms with functor `{}/N' has been changed. The parser from
+  Mercury 0.9 parsed "{1, 2, 3}" as `{}(','(1, ','(2, 3)))'.
+  It is now parsed as `{}(1, 2, 3)'.
 
-* We've added support for tuple types, similar to those in most
-  other functional languages. Tuples use the syntax `{A, B, ...}'.
-  See the "Builtin types" section of the "Types" chapter of the
-  Mercury Language Reference Manual for details.
+* The operator `^' is now used for record syntax, and cannot be
+  used for user-defined functions or constructors.
 
-* The behaviour of the parser__read_term applied to terms with
-  functor `{}/N' has been changed. The parser from Mercury 0.9
-  parsed "{1, 2, 3}" as `{}(','(1, ','(2, 3)))'. It is now
-  parsed as `{}(1, 2, 3)'.
-
 * You can now declare functions by giving a determinism but without
   supplying the modes.  The default function modes will be assumed.
   This is particularly useful for partial functions.
@@ -72,6 +77,13 @@
 * We've added function versions of std_util__solutions,
   std_util__solutions_set, std_util__aggregate, map__search,
   map__insert and map__update.
+
+* We've added functions to allow record syntax to be used
+  with some of the types in the standard library:
+	array__elem/2, 'array__elem :='/3,
+	bt_array__elem/2, 'bt_array__elem :='/3,
+	map__elem/2, 'map__elem :='/3,
+	map__det_elem/2, 'map__det_elem :='/3.
 
 * We've added a pretty printing module, `pprint', to the standard library.
 
Index: compiler/det_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/det_util.m,v
retrieving revision 1.19
diff -u -u -r1.19 det_util.m
--- compiler/det_util.m	2000/10/13 13:55:20	1.19
+++ compiler/det_util.m	2000/11/21 11:25:11
@@ -86,9 +86,12 @@
 :- pred det_info_set_module_info(det_info, module_info, det_info).
 :- mode det_info_set_module_info(in, in, out) is det.
 
-:- func vartypes(det_info) = vartypes.
-:- func 'vartypes:='(det_info, vartypes) = det_info.
+:- pred det_info_get_vartypes(det_info, vartypes).
+:- mode det_info_get_vartypes(in, out) is det.
 
+:- pred det_info_set_vartypes(det_info, vartypes, det_info).
+:- mode det_info_set_vartypes(in, in, out) is det.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -185,6 +188,9 @@
 det_info_get_reorder_conj(DetInfo, DetInfo^reorder_conj).
 det_info_get_reorder_disj(DetInfo, DetInfo^reorder_disj).
 det_info_get_fully_strict(DetInfo, DetInfo^fully_strict).
+det_info_get_vartypes(DetInfo, DetInfo^vartypes).
 
 det_info_set_module_info(DetInfo, ModuleInfo,
 		DetInfo^module_info := ModuleInfo).
+det_info_set_vartypes(DetInfo, VarTypes,
+		DetInfo^vartypes := VarTypes).
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.87
diff -u -u -r1.87 hlds_pred.m
--- compiler/hlds_pred.m	2000/11/23 04:32:22	1.87
+++ compiler/hlds_pred.m	2000/12/03 12:53:03
@@ -2135,11 +2135,11 @@
 
 field_access_function_name(get, FieldName, FieldName).
 field_access_function_name(set, FieldName, FuncName) :-
-	add_sym_name_suffix(FieldName, ":=", FuncName).
+	add_sym_name_suffix(FieldName, " :=", FuncName).
 
 is_field_access_function_name(ModuleInfo, FuncName, Arity,
 		AccessType, FieldName) :-
-	( remove_sym_name_suffix(FuncName, ":=", FieldName0) ->
+	( remove_sym_name_suffix(FuncName, " :=", FieldName0) ->
 		Arity = 2,
 		AccessType = set,
 		FieldName = FieldName0
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.359
diff -u -u -r1.359 make_hlds.m
--- compiler/make_hlds.m	2000/11/17 17:47:42	1.359
+++ compiler/make_hlds.m	2000/12/03 14:20:23
@@ -5452,7 +5452,7 @@
 			FieldValueTerm = RHSTerm
 		}
 	->
-		{ parse_field_name_list(FieldNameTerm, MaybeFieldNames) },
+		{ parse_field_list(FieldNameTerm, MaybeFieldNames) },
 		(
 			{ MaybeFieldNames = ok(FieldNames) },
 			{ ArgTerms = [FieldValueTerm, TermInputTerm,
@@ -5503,7 +5503,7 @@
 	).
 
 :- pred transform_dcg_record_syntax_2(field_access_type,
-		list(ctor_field_name), list(prog_term), prog_context,
+		field_list, list(prog_term), prog_context,
 		prog_varset, hlds_goal, prog_varset,
 		transform_info, transform_info, io__state, io__state).
 :- mode transform_dcg_record_syntax_2(in, in, in, in, in, out, out,
@@ -5518,7 +5518,8 @@
 			expand_set_field_function_call(Context, explicit, [],
 				FieldNames, FieldValueVar, TermInputVar,
 				TermOutputVar, VarSet1, VarSet2, Functor,
-				InnermostFunctor - InnermostSubContext, Goal0),
+				InnermostFunctor - InnermostSubContext, Goal0,
+				Info0, Info1, IO0, IO1),
 
 
 			FieldArgNumber = 2,
@@ -5545,13 +5546,14 @@
 			],
 			insert_arg_unifications_with_supplied_contexts(ArgVars,
 				ArgTerms, ArgContexts, Context, Goal0, VarSet2,
-				Goal, VarSet, Info0, Info, IO0, IO)
+				Goal, VarSet, Info1, Info, IO1, IO)
 		;
 			AccessType = get,
 			expand_dcg_field_extraction_goal(Context, explicit,
 				[], FieldNames, FieldValueVar, TermInputVar,
 				TermOutputVar, VarSet1, VarSet2, Functor,
-				InnermostFunctor - _InnerSubContext, Goal0),
+				InnermostFunctor - _InnerSubContext, Goal0,
+				Info0, Info1, IO0, IO1),
 			InputTermArgNumber = 1,
 			InputTermArgContext = functor(Functor, explicit, []),
 
@@ -5576,7 +5578,7 @@
 			],
 			insert_arg_unifications_with_supplied_contexts(ArgVars,
 				ArgTerms, ArgContexts, Context, Goal0, VarSet2,
-				Goal, VarSet, Info0, Info, IO0, IO)
+				Goal, VarSet, Info1, Info, IO1, IO)
 		)
 	;
 		error("make_hlds__do_transform_dcg_record_syntax")
@@ -5594,70 +5596,86 @@
 	%
 :- pred expand_set_field_function_call(prog_context,
 		unify_main_context, unify_sub_contexts,
-		list(ctor_field_name), prog_var, prog_var,
+		field_list, prog_var, prog_var,
 		prog_var, prog_varset, prog_varset, cons_id,
-		pair(cons_id, unify_sub_contexts), hlds_goal).
+		pair(cons_id, unify_sub_contexts), hlds_goal,
+		transform_info, transform_info, io__state, io__state).
 :- mode expand_set_field_function_call(in, in, in, in, in, in,
-		in, in, out, out, out, out) is det.
+		in, in, out, out, out, out, in, out, di, uo) is det.
 
 expand_set_field_function_call(Context, MainContext, SubContext0,
 		FieldNames, FieldValueVar, TermInputVar,
 		TermOutputVar, VarSet0, VarSet,
-		Functor, FieldSubContext, Goal) :-
+		Functor, FieldSubContext, Goal, Info0, Info) -->
 	expand_set_field_function_call_2(Context, MainContext,
 		SubContext0, FieldNames, FieldValueVar, TermInputVar,
 		TermOutputVar, VarSet0, VarSet,
-		Functor, FieldSubContext, Goals),
-	wrap_field_access_goals(Context, Goals, Goal).
+		Functor, FieldSubContext, Goals, Info0, Info),
+	{ wrap_field_access_goals(Context, Goals, Goal) }.
 
 :- pred expand_set_field_function_call_2(prog_context,
 		unify_main_context, unify_sub_contexts,
-		list(ctor_field_name), prog_var, prog_var,
+		field_list, prog_var, prog_var,
 		prog_var, prog_varset, prog_varset, cons_id,
-		pair(cons_id, unify_sub_contexts), list(hlds_goal)).
+		pair(cons_id, unify_sub_contexts), list(hlds_goal),
+		transform_info, transform_info, io__state, io__state).
 :- mode expand_set_field_function_call_2(in, in, in, in, in, in,
-		in, in, out, out, out, out) is det.
+		in, in, out, out, out, out, in, out, di, uo) is det.
 
-expand_set_field_function_call_2(_, _, _, [], _, _, _, _, _, _, _, _) :-
-	error("expand_set_field_function_call_2: empty list of field names").
+expand_set_field_function_call_2(_, _, _, [], _, _, _, _, _, _, _, _, _, _) -->
+	{ error(
+	"expand_set_field_function_call_2: empty list of field names") }.
 expand_set_field_function_call_2(Context, MainContext, SubContext0,
-		[FieldName | FieldNames], FieldValueVar, TermInputVar,
-		TermOutputVar, VarSet0, VarSet, Functor, FieldSubContext,
-		Goals) :-
-	( FieldNames = [_|_] ->
-		varset__new_var(VarSet0, SubTermInputVar, VarSet1),
-		varset__new_var(VarSet1, SubTermOutputVar, VarSet2),
-
-		construct_field_access_function_call(set, Context,
+		[FieldName - FieldArgs | FieldNames], FieldValueVar,
+		TermInputVar, TermOutputVar, VarSet0, VarSet, Functor,
+		FieldSubContext, Goals, Info0, Info) -->
+	{ make_fresh_arg_vars(FieldArgs, VarSet0, FieldArgVars, VarSet1) },
+	( { FieldNames = [_|_] } ->
+		{ varset__new_var(VarSet1, SubTermInputVar, VarSet2) },
+		{ varset__new_var(VarSet2, SubTermOutputVar, VarSet3) },
+		{ SetArgs = list__append(FieldArgVars,
+				[TermInputVar, SubTermOutputVar]) },
+		{ construct_field_access_function_call(set, Context,
 			MainContext, SubContext0, FieldName,
-			TermOutputVar, [TermInputVar, SubTermOutputVar],
-			Functor, UpdateGoal),
+			TermOutputVar, SetArgs,
+			Functor, UpdateGoal) },
 
 		% extract the field containing the field to update.
-		construct_field_access_function_call(get, Context, MainContext,
-			SubContext0, FieldName, SubTermInputVar,
-			[TermInputVar], _, GetSubFieldGoal),
+		{ construct_field_access_function_call(get, Context,
+			MainContext, SubContext0, FieldName, SubTermInputVar,
+			list__append(FieldArgVars, [TermInputVar]), _,
+			GetSubFieldGoal) },
 
 		% recursively update the field.
-		SubTermInputArgNumber = 2,
-		TermInputContext = Functor - SubTermInputArgNumber,
-		SubContext = [TermInputContext | SubContext0],
+		{ SubTermInputArgNumber = 2 + list__length(FieldArgs) },
+		{ TermInputContext = Functor - SubTermInputArgNumber },
+		{ SubContext = [TermInputContext | SubContext0] },
 		expand_set_field_function_call_2(Context, MainContext,
 			SubContext, FieldNames, FieldValueVar, SubTermInputVar,
-			SubTermOutputVar, VarSet2, VarSet, _,
-			FieldSubContext, Goals0),
+			SubTermOutputVar, VarSet3, VarSet4, _,
+			FieldSubContext, Goals0, Info0, Info1),
 
-		list__append([GetSubFieldGoal | Goals0], [UpdateGoal], Goals)
+		{ list__append([GetSubFieldGoal | Goals0],
+			[UpdateGoal], Goals1) }
 	;
-		VarSet = VarSet0,
-		construct_field_access_function_call(set, Context,
-			MainContext, SubContext0, FieldName,
-			TermOutputVar, [TermInputVar, FieldValueVar],
-			Functor, Goal),
-		FieldSubContext = Functor - SubContext0,
-		Goals = [Goal]
-	).
+		{ VarSet4 = VarSet1 },
+		{ SetArgs = list__append(FieldArgVars,
+				[TermInputVar, FieldValueVar]) },
+		{ construct_field_access_function_call(set, Context,
+			MainContext, SubContext0, FieldName, TermOutputVar,
+			SetArgs, Functor, Goal) },
+		{ FieldSubContext = Functor - SubContext0 },
+		{ Info1 = Info0 },
+		{ Goals1 = [Goal] }
 
+	),
+	{ ArgContext = functor(Functor, MainContext, SubContext0) },
+	{ goal_info_init(Context, GoalInfo) },
+	{ conj_list_to_goal(Goals1, GoalInfo, Conj0) },
+	append_arg_unifications(FieldArgVars, FieldArgs, Context, ArgContext,
+		Conj0, VarSet4, Conj, VarSet, Info1, Info),
+	{ goal_to_conj_list(Conj, Goals) }.
+
 	% Expand a field extraction goal into a list of goals which
 	% each get one level of the structure.
 	%
@@ -5671,26 +5689,28 @@
 	%	ModuleName = V_2 ^ module_name.
 	%
 :- pred expand_dcg_field_extraction_goal(prog_context, unify_main_context,
-		unify_sub_contexts, list(ctor_field_name), prog_var, prog_var,
+		unify_sub_contexts, field_list, prog_var, prog_var,
 		prog_var, prog_varset, prog_varset, cons_id,
-		pair(cons_id, unify_sub_contexts), hlds_goal).
+		pair(cons_id, unify_sub_contexts), hlds_goal,
+		transform_info, transform_info, io__state, io__state).
 :- mode expand_dcg_field_extraction_goal(in, in, in, in, in,
-		in, in, in, out, out, out, out) is det.
+		in, in, in, out, out, out, out, in, out, di, uo) is det.
 
 expand_dcg_field_extraction_goal(Context, MainContext, SubContext,
 		FieldNames, FieldValueVar, TermInputVar, TermOutputVar,
-		VarSet0, VarSet, Functor, FieldSubContext, Goal) :-
+		VarSet0, VarSet, Functor, FieldSubContext,
+		Goal, Info0, Info) -->
 	% unify the DCG input and output variables
-	create_atomic_unification(TermOutputVar, var(TermInputVar),
-			Context, MainContext, SubContext, UnifyDCG),
+	{ create_atomic_unification(TermOutputVar, var(TermInputVar),
+			Context, MainContext, SubContext, UnifyDCG) },
 
 	% process the access function as a get function on
 	% the output DCG variable
 	expand_get_field_function_call_2(Context, MainContext, SubContext,
-		FieldNames, FieldValueVar, TermOutputVar,
-		VarSet0, VarSet, Functor, FieldSubContext, Goals1),
-	Goals = [UnifyDCG | Goals1],
-	wrap_field_access_goals(Context, Goals, Goal).
+		FieldNames, FieldValueVar, TermOutputVar, VarSet0, VarSet,
+		Functor, FieldSubContext, Goals1, Info0, Info),
+	{ Goals = [UnifyDCG | Goals1] },
+	{ wrap_field_access_goals(Context, Goals, Goal) }.
 	
 	% Expand a field extraction function call into a list of goals which
 	% each get one level of the structure.
@@ -5703,54 +5723,68 @@
 	%	ModuleName = V_2 ^ module_name.
 	%
 :- pred expand_get_field_function_call(prog_context, unify_main_context,
-		unify_sub_contexts, list(ctor_field_name), prog_var,
+		unify_sub_contexts, field_list, prog_var,
 		prog_var, prog_varset, prog_varset, cons_id,
-		pair(cons_id, unify_sub_contexts), hlds_goal).
+		pair(cons_id, unify_sub_contexts), hlds_goal,
+		transform_info, transform_info, io__state, io__state).
 :- mode expand_get_field_function_call(in, in, in, in, in,
-		in, in, out, out, out, out) is det.
+		in, in, out, out, out, out, in, out, di, uo) is det.
 
 expand_get_field_function_call(Context, MainContext, SubContext0,
-		FieldNames, FieldValueVar, TermInputVar,
-		VarSet0, VarSet, Functor, FieldSubContext, Goal) :-
+		FieldNames, FieldValueVar, TermInputVar, VarSet0, VarSet,
+		Functor, FieldSubContext, Goal, Info0, Info) -->
 	expand_get_field_function_call_2(Context, MainContext, SubContext0,
 		FieldNames, FieldValueVar, TermInputVar,
-		VarSet0, VarSet, Functor, FieldSubContext, Goals),
-	wrap_field_access_goals(Context, Goals, Goal).
+		VarSet0, VarSet, Functor, FieldSubContext, Goals, Info0, Info),
+	{ wrap_field_access_goals(Context, Goals, Goal) }.
 
 :- pred expand_get_field_function_call_2(prog_context, unify_main_context,
-		unify_sub_contexts, list(ctor_field_name), prog_var,
+		unify_sub_contexts, field_list, prog_var,
 		prog_var, prog_varset, prog_varset, cons_id,
-		pair(cons_id, unify_sub_contexts), list(hlds_goal)).
+		pair(cons_id, unify_sub_contexts), list(hlds_goal),
+		transform_info, transform_info, io__state, io__state).
 :- mode expand_get_field_function_call_2(in, in, in, in, in,
-		in, in, out, out, out, out) is det.
+		in, in, out, out, out, out, in, out, di, uo) is det.
 
-expand_get_field_function_call_2(_, _, _, [], _, _, _, _, _, _, _) :-
-	error("expand_get_field_function_call_2: empty list of field names").
+expand_get_field_function_call_2(_, _, _, [], _, _, _, _, _, _, _, _, _) -->
+	{ error(
+	"expand_get_field_function_call_2: empty list of field names") }.
 expand_get_field_function_call_2(Context, MainContext, SubContext0,
-		[FieldName | FieldNames], FieldValueVar, TermInputVar,
-		VarSet0, VarSet, Functor, FieldSubContext, Goals) :-
-	( FieldNames = [_|_] ->
-		varset__new_var(VarSet0, SubTermInputVar, VarSet1),
-		construct_field_access_function_call(get, Context, MainContext,
-			SubContext0, FieldName, SubTermInputVar,
-			[TermInputVar], Functor, Goal),
+		[FieldName - FieldArgs | FieldNames], FieldValueVar,
+		TermInputVar, VarSet0, VarSet, Functor,
+		FieldSubContext, Goals, Info0, Info) -->
+	{ make_fresh_arg_vars(FieldArgs, VarSet0, FieldArgVars, VarSet1) },
+	{ GetArgVars = list__append(FieldArgVars, [TermInputVar]) },
+	( { FieldNames = [_|_] } ->
+		{ varset__new_var(VarSet1, SubTermInputVar, VarSet2) },
+		{ construct_field_access_function_call(get, Context,
+			MainContext, SubContext0, FieldName, SubTermInputVar,
+			GetArgVars, Functor, Goal) },
 
 		% recursively extract until we run out of field names
-		TermInputArgNumber = 1,
-		TermInputContext = Functor - TermInputArgNumber,
-		SubContext = [TermInputContext | SubContext0],
+		{ TermInputArgNumber = 1 + list__length(FieldArgVars) },
+		{ TermInputContext = Functor - TermInputArgNumber },
+		{ SubContext = [TermInputContext | SubContext0] },
 		expand_get_field_function_call_2(Context, MainContext,
 			SubContext, FieldNames, FieldValueVar, SubTermInputVar,
-			VarSet1, VarSet, _, FieldSubContext, Goals1),
-		Goals = [Goal | Goals1]
-	;
-		VarSet = VarSet0,
-		FieldSubContext = Functor - SubContext0,
-		construct_field_access_function_call(get, Context, MainContext,
-			SubContext0, FieldName, FieldValueVar,
-			[TermInputVar], Functor, Goal),
-		Goals = [Goal]
-	).
+			VarSet2, VarSet3, _, FieldSubContext,
+			Goals1, Info0, Info1),
+		{ Goals2 = [Goal | Goals1] }
+	;
+		{ VarSet3 = VarSet1 },
+		{ FieldSubContext = Functor - SubContext0 },
+		{ construct_field_access_function_call(get, Context,
+			MainContext, SubContext0, FieldName, FieldValueVar,
+			GetArgVars, Functor, Goal) },
+		{ Info1 = Info0 },
+		{ Goals2 = [Goal] }
+	),
+	{ ArgContext = functor(Functor, MainContext, SubContext0) },
+	{ goal_info_init(Context, GoalInfo) },
+	{ conj_list_to_goal(Goals2, GoalInfo, Conj0) },
+	append_arg_unifications(FieldArgVars, FieldArgs, Context, ArgContext,
+		Conj0, VarSet3, Conj, VarSet, Info1, Info),
+	{ goal_to_conj_list(Conj, Goals) }.
 
 :- pred construct_field_access_function_call(field_access_type, prog_context,
 		unify_main_context, unify_sub_contexts, ctor_field_name,
@@ -5784,12 +5818,14 @@
 		Conj = conj(Goals) - GoalInfo,
 		Goal = some([], can_remove, Conj) - GoalInfo
 	).
+
+:- type field_list == assoc_list(ctor_field_name, list(prog_term)).
 
-:- pred parse_field_name_list(prog_term,
-		maybe1(list(ctor_field_name), prog_var_type)).
-:- mode parse_field_name_list(in, out) is det.
+:- pred parse_field_list(prog_term,
+		maybe1(field_list, prog_var_type)).
+:- mode parse_field_list(in, out) is det.
 
-parse_field_name_list(Term, MaybeFieldNames) :-
+parse_field_list(Term, MaybeFieldNames) :-
 	(
 		Term = term__functor(term__atom("^"),
 			[FieldNameTerm, OtherFieldNamesTerm], _)
@@ -5797,9 +5833,9 @@
 		(
 			parse_qualified_term(FieldNameTerm, FieldNameTerm,
 				"field name", Result),
-			Result = ok(FieldName, [])
+			Result = ok(FieldName, Args)
 		->
-			parse_field_name_list(OtherFieldNamesTerm,
+			parse_field_list(OtherFieldNamesTerm,
 				MaybeFieldNames1),
 			(
 				MaybeFieldNames1 = error(_, _),
@@ -5807,7 +5843,7 @@
 			;
 				MaybeFieldNames1 = ok(FieldNames1),
 				MaybeFieldNames =
-					ok([FieldName | FieldNames1])
+					ok([FieldName - Args | FieldNames1])
 			)
 		;
 			MaybeFieldNames = error("expected field name",
@@ -5816,9 +5852,9 @@
 	;
 		(
 			parse_qualified_term(Term, Term, "field name", Result),
-			Result = ok(FieldName, [])
+			Result = ok(FieldName, Args)
 		->
-			MaybeFieldNames = ok([FieldName])
+			MaybeFieldNames = ok([FieldName - Args])
 		;	
 			MaybeFieldNames = error("expected field name",
 				Term)
@@ -6832,27 +6868,27 @@
 		% handle field extraction expressions
 		{ F = term__atom("^") },
 		{ Args = [InputTerm, FieldNameTerm] },
-		{ parse_field_name_list(FieldNameTerm, FieldNameResult) },
+		{ parse_field_list(FieldNameTerm, FieldNameResult) },
 		{ FieldNameResult = ok(FieldNames) }
 	->
 		check_expr_purity(Purity, Context, Info0, Info1),
 		{ make_fresh_arg_var(InputTerm, InputTermVar, [],
 			VarSet0, VarSet1) },
-		{ expand_get_field_function_call(Context, MainContext,
+		expand_get_field_function_call(Context, MainContext,
 			SubContext, FieldNames, X, InputTermVar,
-			VarSet1, VarSet2, Functor, _, Goal0) },
+			VarSet1, VarSet2, Functor, _, Goal0, Info1, Info2),
 
 		{ ArgContext = functor(Functor, MainContext, SubContext) },
 		append_arg_unifications([InputTermVar], [InputTerm],
 			FunctorContext, ArgContext, Goal0,
-			VarSet2, Goal, VarSet, Info1, Info)
+			VarSet2, Goal, VarSet, Info2, Info)
 	;
 		% handle field update expressions
 		{ F = term__atom(":=") },
 		{ Args = [FieldDescrTerm, FieldValueTerm] },
 		{ FieldDescrTerm = term__functor(term__atom("^"),
 			[InputTerm, FieldNameTerm], _) },
-		{ parse_field_name_list(FieldNameTerm, FieldNameResult) },
+		{ parse_field_list(FieldNameTerm, FieldNameResult) },
 		{ FieldNameResult = ok(FieldNames) }
 	->
 		check_expr_purity(Purity, Context, Info0, Info1),
@@ -6861,23 +6897,23 @@
 		{ make_fresh_arg_var(FieldValueTerm, FieldValueVar,
 			[InputTermVar], VarSet1, VarSet2) },
 
-		{ expand_set_field_function_call(Context, MainContext,
+		expand_set_field_function_call(Context, MainContext,
 			SubContext, FieldNames, FieldValueVar, InputTermVar, X,
 			VarSet2, VarSet3, Functor,
-			InnerFunctor - FieldSubContext, Goal0) },
+			InnerFunctor - FieldSubContext, Goal0, Info1, Info2),
 
 		{ TermArgContext = functor(Functor, MainContext, SubContext) },
 		{ TermArgNumber = 1 },
 		append_arg_unification(InputTermVar, InputTerm,
 			FunctorContext, TermArgContext, TermArgNumber,
-			TermUnifyConj, VarSet3, VarSet4, Info1, Info2),
+			TermUnifyConj, VarSet3, VarSet4, Info2, Info3),
 
 		{ FieldArgContext = functor(InnerFunctor,
 			MainContext, FieldSubContext) },
 		{ FieldArgNumber = 2 },
 		append_arg_unification(FieldValueVar, FieldValueTerm,
 			FunctorContext, FieldArgContext, FieldArgNumber,
-			FieldUnifyConj, VarSet4, VarSet, Info2, Info),
+			FieldUnifyConj, VarSet4, VarSet, Info3, Info),
 
 		{ Goal0 = _ - GoalInfo0 },
 		{ goal_to_conj_list(Goal0, GoalList0) },
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.91
diff -u -u -r1.91 simplify.m
--- compiler/simplify.m	2000/11/19 12:43:31	1.91
+++ compiler/simplify.m	2000/11/21 11:25:09
@@ -2089,7 +2089,8 @@
 simplify_info_get_common_info(SI, SI^common_info).
 simplify_info_get_instmap(SI, SI^instmap).
 simplify_info_get_varset(SI, SI^varset).
-simplify_info_get_var_types(SI, SI^det_info^vartypes).
+simplify_info_get_var_types(SI, VarTypes) :-
+	det_info_get_vartypes(SI^det_info, VarTypes).
 simplify_info_requantify(SI) :-
 	SI^requantify = yes.
 simplify_info_recompute_atomic(SI) :-
@@ -2163,7 +2164,8 @@
 simplify_info_set_instmap(SI, InstMap, SI^instmap := InstMap). 
 simplify_info_set_common_info(SI, Common, SI^common_info := Common). 
 simplify_info_set_varset(SI, VarSet, SI^varset := VarSet). 
-simplify_info_set_var_types(SI, VarTypes, SI^det_info^vartypes := VarTypes).
+simplify_info_set_var_types(SI, VarTypes, SI^det_info := DetInfo) :-
+	det_info_set_vartypes(SI ^ det_info, VarTypes, DetInfo).
 simplify_info_set_requantify(SI, SI^requantify := yes).
 simplify_info_set_recompute_atomic(SI, SI^recompute_atomic := yes).
 simplify_info_set_rerun_det(SI, SI^rerun_det := yes).
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.294
diff -u -u -r1.294 typecheck.m
--- compiler/typecheck.m	2000/11/17 17:48:46	1.294
+++ compiler/typecheck.m	2000/12/03 12:55:20
@@ -760,7 +760,7 @@
 	%
 	% For a field access function for which the user has supplied
 	% a declaration but no clauses, add a clause
-	% 'foo:='(X, Y) = 'foo:='(X, Y).
+	% 'foo :='(X, Y) = 'foo :='(X, Y).
 	% As for the default clauses added for builtins, this is not a
 	% recursive call -- post_typecheck.m will expand the body into
 	% unifications.
@@ -2804,7 +2804,7 @@
 	% builtin_field_access_function_type(TypeCheckInfo, Functor,
 	%	Arity, ConsTypeInfos):
 	% Succeed if Functor is the name of one the automatically
-	% generated field access functions (fieldname, '<fieldname>:=').
+	% generated field access functions (fieldname, '<fieldname> :=').
 :- pred builtin_field_access_function_type(typecheck_info, cons_id, arity,
 		list(cons_type_info), list(invalid_field_update)).
 :- mode builtin_field_access_function_type(typecheck_info_ui, in, in,
@@ -2924,7 +2924,7 @@
 	AccessType = set,
 
 	%
-	% A `'field:='/2' function has no existentially
+	% A `'field :='/2' function has no existentially
 	% quantified type variables - the values of all
 	% type variables in the field are supplied by
 	% the caller, all the others are supplied by
@@ -3019,7 +3019,7 @@
 			% Rename the class constraints, projecting
 			% the constraints onto the set of type variables
 			% occuring in the types of the arguments of
-			% the call to `'field:='/2'. 
+			% the call to `'field :='/2'. 
 			%
 			term__vars_list([FunctorType, FieldType],
 				CallTVars0),
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.199
diff -u -u -r1.199 reference_manual.texi
--- doc/reference_manual.texi	2000/11/17 05:52:47	1.199
+++ doc/reference_manual.texi	2000/12/05 01:50:53
@@ -353,9 +353,9 @@
 That is, a term such as @code{Term(Arg1, @dots{}, ArgN)} is
 parsed as @code{''(Term, Arg1, @dots{}, ArgN)}.
 Note that the closure term can be a parenthesized
-term; for example, @code{(Term^FieldName)(Arg1, Arg2)}
+term; for example, @code{(Term ^ FieldName)(Arg1, Arg2)}
 is a higher-order term, and so it gets parsed as
-if it were @code{''((Term^FieldName), Arg1, Arg2)}.
+if it were @code{''((Term ^ FieldName), Arg1, Arg2)}.
 
 @node Builtin Operators
 @section Builtin Operators
@@ -855,33 +855,31 @@
 transform(V_in, V_out, :=(Term)) = (V_out = Term)
 @end example
 
- at item @var{Term} =^ @var{field1} ^ @dots{} ^ @var{fieldN}
+ at item @var{Term} =^ @var{field_list}
 A DCG field selection.
-Unifies @var{Term} with the result of applying the functions
- at var{field1} @dots{} @var{fieldN} to the implicit DCG argument.
+Unifies @var{Term} with the result of applying the field
+selection @var{field_list} to the implicit DCG argument.
 @var{Term} must be a valid data-term.
-For each @var{field} in @w{@var{field1} @dots{} @var{fieldN}} there must be
-a visible function named @samp{@var{field}/1}.
+ at var{field_list} must be a valid field list.
 @xref{Record syntax}.
 
 Semantics:
 @example
-transform(V_in, V_out, Term =^ field1 ^ @dots{} ^ fieldN) =
-        (Term = V_in ^ field1 ^ @dots{} ^ fieldN, V_out = V_in)
+transform(V_in, V_out, Term =^ field_list
+        (Term = V_in ^ field_list = V_in)
 @end example
 
- at item ^ @var{field} := @var{Term}
+ at item ^ @var{field_list} := @var{Term}
 A DCG field update.
 Replaces a field in the implicit DCG argument. 
 @var{Term} must be a valid data-term.
-For each @var{field} in @w{@var{field1} @dots{} @var{fieldN}} there must be
-visible functions named @samp{@var{field}/1} and @samp{'@var{field}:='/2}.
+ at var{field_list} must be a valid field list.
 @xref{Record syntax}.
 
 Semantics:
 @example
-transform(V_in, V_out, ^ field1 ^ @dots{} ^ fieldN := Term) =
-        (V_out = V_in ^ field1 ^ @dots{} ^ fieldN := Term)
+transform(V_in, V_out, ^ field_list := Term) =
+        (V_out = V_in ^ field_list := Term)
 @end example
 
 @item @var{DCG-call}
@@ -944,51 +942,82 @@
 
 Record syntax provides a convenient way to select or update fields
 of data constructors, independent of the definition of the constructor.
-
 Record syntax expressions are transformed into sequences of calls
 to field selection or update functions (@pxref{Field access functions}).
 
+A field specifier is a name or a compound data-term.
+A field list is a list of field specifiers separated by @code{^}.
+ at code{field}, @code{field1 ^ field2} and @code{field1(A) ^ field2(B, C)} are
+all valid field lists.
+
+If the top-level functor of a field specifier is @samp{@var{field}/N},
+there must be a visible selection function @samp{@var{field}/(N + 1)}. If the
+field specifier occurs in a field update expression, there must also be a
+visible update function named @samp{'@var{field} :='/(N + 2)}. 
+
 Record syntax expressions have one of the following forms.
 There are also record syntax DCG goals (@pxref{DCG-goals}),
 which provide similar functionality to record syntax expressions,
 except that they act on the DCG arguments of a DCG clause.
 
 @table @code
- at item @var{Term} ^ @var{field}
+ at item @var{Term} ^ @var{field_list}
 
-A field selection, equivalent to @code{@var{field}(@var{Term})}.
+A field selection. For each field specifier in @var{field_list}, apply
+the corresponding selection function in turn.
 
 @var{Term} must be a valid data-term.
- at var{field} must be the name of a visible unary function, possibly a
-function generated for a labelled field of a data constructor.
+ at var{field_list} must be a valid field list.
+
+A field selection is transformed using the following rules:
+ at example
+transform(Term ^ Field(Arg1, @dots{})) = Field(Arg1, @dots{}, Term).
+transform(Term ^ Field(Arg1, @dots{}) ^ Rest) =
+                transform(Field(Arg1, @dots{}) ^ Rest).
+ at end example
+
+Examples:
+
+ at code{Term ^ field} is equivalent to @code{field(Term)}.
 
-Field selections may be chained, as in @code{Term ^ field1 ^ field2},
-which is equivalent to @code{field2(field1(Term))}.
+ at code{Term ^ field(Arg)} is equivalent to @code{field(Arg, Term)}.
 
- at item @var{Term} ^ @var{field1} ^ @dots{} ^ @var{fieldN} := @var{FieldValue}
+ at w{@code{Term ^ field1(Arg1) ^ field2(Arg2, Arg3)}} is equivalent
+to @w{@code{field2(Arg2, Arg3, field1(Arg1, Term))}}.
 
-A field update.
+ at item @var{Term} ^ @var{field_list} := @var{FieldValue}
 
+A field update, returning a copy of @var{Term} with the value of
+the field specified by @var{field_list} replaced with @var{FieldValue}.
+
 @var{Term} must be a valid data-term.
-For each @var{field} in @w{@var{field1} @dots{} @var{fieldN}} there must be
-visible functions named @samp{@var{field}/1} and @samp{'@var{field}:='/2}.
-Typically, these functions will be automatically generated by the compiler
-for a labelled field of a data constructor, although they may be supplied
-by the user.
-
-The term @code{Term ^ field := FieldValue} is equivalent
-to @code{'field:='(Term, FieldValue)}.
-
-The general case above is equivalent to the code:
- at example
-OldField1 = @var{field1}(Term),
-OldField2 = @var{field2}(OldField1),
- at dots{}
-OldField_N_Minus_1 = @var{field_N_Minus_2}(OldField_N_Minus_2),
-NewField_N_Minus_1 = '@var{fieldN}:='(OldField_N_Minus_1, FieldValue),
- at dots{}
-NewField1 = '@var{field2}:='(OldField1, NewField2),
-Result = '@var{field1}:='(Term, NewField1)
+ at var{field_list} must be a valid field list.
+
+A field update is transformed using the following rules:
+ at example
+transform(Term ^ Field(Arg1, @dots{}) := FieldValue) =
+                'Field :='(Arg1, @dots{}, Term, FieldValue)).
+
+transform(Term0 ^ Field(Arg1, @dots{}) ^ Rest := FieldValue) = Term :-
+        OldFieldValue = Field(Arg1, @dots{}, Term0),
+        NewFieldValue = transform(OldFieldValue ^ Rest := FieldValue),
+        Term = 'Field :='(Arg1, @dots{}, Term, NewFieldValue).
+ at end example
+
+Examples:
+
+ at w{@code{Term ^ field := FieldValue}} is equivalent
+to @w{@code{'field :='(Term, FieldValue)}}.
+
+ at w{@code{Term ^ field(Arg) := FieldValue}} is equivalent
+to @w{@code{'field :='(Arg, Term, FieldValue)}}.
+
+ at w{@code{Term ^ field1(Arg1) ^ field2(Arg2) := FieldValue}} is equivalent
+to the code 
+ at example
+OldField1 = field1(Arg1, Term),
+NewField1 = 'field2 :='(Arg2, OldField1, FieldValue),
+Result = 'field1 :='(Arg1, OldField1, NewField1)
 @end example
 
 @end table
@@ -1569,16 +1598,16 @@
 @subsection Field update
 
 @example
-'@var{field}:='(@var{Term}, @var{ValueTerm})
+'@var{field} :='(@var{Term}, @var{ValueTerm})
 @end example
 
 Each field label @samp{@var{field}} in a constructor causes generation
-of a field update function @samp{'@var{field}:='/2}.
+of a field update function @samp{'@var{field} :='/2}.
 The first argument of this function is a data-term of the same type as the
 constructor. The second argument is a data-term of the same type as the
 labelled field. The return value is a copy of the first argument with
 value of the labelled field replaced by the second argument.
- at samp{'@var{field}:='/2} fails if the top-level constructor of the
+ at samp{'@var{field} :='/2} fails if the top-level constructor of the
 first argument is not the constructor containing the labelled field.
 
 If the declaration of the field is in the interface section of the module,
@@ -1626,6 +1655,17 @@
 as part of a type is now computed each time it is requested. It also
 allows record syntax to be used for type class methods.
 
+User-declared field access functions may take extra arguments.
+For example, the Mercury standard library module @code{map} contains
+the following functions:
+ at example
+:- func elem(K, map(K, V)) = V is semidet.
+:- func 'elem :='(K, map(K, V), V) = map(K, V).
+ at end example
+
+The Mercury standard library modules @code{array} and @code{bt_array}
+define similar functions.
+
 @node Field access examples
 @subsection Field access examples
 
@@ -1653,8 +1693,8 @@
 :- func field1(type1) = type2.
 field1(type1(Field1, _)) = Field1.
 
-:- func 'field1:='(type1, type2) = type1.
-'field1:='(type1(_, Field2), Field1) = type1(Field1, Field2).
+:- func 'field1 :='(type1, type2) = type1.
+'field1 :='(type1(_, Field2), Field1) = type1(Field1, Field2).
 @end example
 
 Using these functions and the syntactic sugar described in
@@ -1664,7 +1704,7 @@
 :- func increment_field3(type1) = type1.
 
 increment_field3(Term0) =
-        Term0^field1^field3 := Term0^field1^field3 + 1.
+        Term0 ^ field1 ^ field3 := Term0 ^ field1 ^ field3 + 1.
 @end example
 
 The compiler expands this into
@@ -1674,8 +1714,19 @@
         OldField3 = field3(field1(Term0)),
 
         OldField1 = field1(Term0),
-        NewField1 = 'field3:='(OldField1, OldField3 + 1),
-        Term = 'field1:='(Term0, NewField1).
+        NewField1 = 'field3 :='(OldField1, OldField3 + 1),
+        Term = 'field1 :='(Term0, NewField1).
+ at end example
+
+The field access functions defined in the Mercury standard library
+module @samp{map} can be used as follows:
+
+ at example
+:- func update_field_in_map(map(int, type1), int, string)
+                = map(int, type1) is semidet.
+
+update_field_in_map(Map, Index, Value) =
+                Map ^ elem(Index) ^ field2 := Value.
 @end example
 
 @node Modes
Index: library/array.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/array.m,v
retrieving revision 1.79
diff -u -u -r1.79 array.m
--- library/array.m	2000/12/03 02:22:44	1.79
+++ library/array.m	2000/12/04 14:39:17
@@ -188,6 +188,19 @@
 :- mode array__semidet_slow_set(array_ui, in, in, array_uo) is semidet.
 :- mode array__semidet_slow_set(in, in, in, array_uo) is semidet.
 
+	% Field selection for arrays.
+	% Array ^ elem(Index) = array__lookup(Array, Index).
+:- func array__elem(int, array(T)) = T.
+:- mode array__elem(in, array_ui) = out is det.
+:- mode array__elem(in, in) = out is det.
+
+	% Field update for arrays.
+	% (Array ^ elem(Index) := Value) = array__set(Array, Index, Value).
+:- func 'array__elem :='(int, array(T), T) = array(T).
+:- mode 'array__elem :='(in, array_ui, in) = array_uo is det.
+
+%-----------------------------------------------------------------------------%
+
 	% array__copy(Array0, Array):
 	% Makes a new unique copy of an array.
 :- pred array__copy(array(T), array(T)).
@@ -892,3 +905,6 @@
 array_compare(A1, A2) = C :-
 	array_compare(C, A1, A2).
 
+array__elem(Index, Array) = array__lookup(Array, Index).
+
+'array__elem :='(Index, Array, Value) = array__set(Array, Index, Value).
Index: library/bt_array.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/bt_array.m,v
retrieving revision 1.8
diff -u -u -r1.8 bt_array.m
--- library/bt_array.m	2000/11/12 08:51:33	1.8
+++ library/bt_array.m	2000/12/04 15:24:42
@@ -173,6 +173,14 @@
 :- pred bt_array__bsearch(bt_array(T), T, pred(T, T, comparison_result), int).
 :- mode bt_array__bsearch(in, in, pred(in, in, out) is det, out) is semidet.
 
+	% Field selection for arrays.
+	% Array ^ elem(Index) = bt_array__lookup(Array, Index).
+:- func bt_array__elem(int, bt_array(T)) = T.
+
+	% Field update for arrays.
+	% (Array ^ elem(Index) := Value) = bt_array__set(Array, Index, Value).
+:- func 'bt_array__elem :='(int, bt_array(T), T) = bt_array(T).
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -690,3 +698,6 @@
 bt_array__fetch_items(BTA, N1, N2) = Xs :-
 	bt_array__fetch_items(BTA, N1, N2, Xs).
 
+bt_array__elem(Index, Array) = bt_array__lookup(Array, Index).
+
+'bt_array__elem :='(Index, Array, Value) = bt_array__set(Array, Index, Value).
Index: library/map.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/map.m,v
retrieving revision 1.78
diff -u -u -r1.78 map.m
--- library/map.m	2000/11/12 08:51:35	1.78
+++ library/map.m	2000/12/04 15:10:41
@@ -331,6 +331,24 @@
 :- func map__det_union(func(V, V) = V, map(K, V), map(K, V)) = map(K, V).
 :- mode map__det_union(func(in, in) = out is semidet, in, in) = out is det.
 
+
+	% Field selection for maps.
+
+	% Map ^ elem(Key) = map__search(Map, Key).
+:- func map__elem(K, map(K, V)) = V is semidet.
+
+	% Map ^ det_elem(Key) = map__lookup(Map, Key).
+:- func map__det_elem(K, map(K, V)) = V. 
+
+
+	% Field update for maps.
+
+	% (Map ^ elem(Key) := Value) = map__set(Map, Key, Value).
+:- func 'map__elem :='(K, map(K, V), V) = map(K, V).
+
+	% (Map ^ elem(Key) := Value) = map__det_update(Map, Key, Value).
+:- func 'map__det_elem :='(K, map(K, V), V) = map(K, V).
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -836,3 +854,11 @@
 map__det_union(F, M1, M2) = M3 :-
 	P = ( pred(X::in, Y::in, Z::out) is semidet :- Z = F(X, Y) ),
 	map__det_union(P, M1, M2, M3).
+
+map__elem(Key, Map) = map__search(Map, Key).
+
+map__det_elem(Key, Map) = map__lookup(Map, Key).
+
+'map__elem :='(Key, Map, Value) = map__set(Map, Key, Value).
+
+'map__det_elem :='(Key, Map, Value) = map__det_update(Map, Key, Value).
Index: tests/hard_coded/typeclasses/record_syntax.exp
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/record_syntax.exp,v
retrieving revision 1.2
diff -u -u -r1.2 record_syntax.exp
--- tests/hard_coded/typeclasses/record_syntax.exp	2000/09/15 05:18:48	1.2
+++ tests/hard_coded/typeclasses/record_syntax.exp	2000/12/05 01:34:23
@@ -13,8 +13,10 @@
 Pair0 ^ fst = 1
 Pair = "new first elem" - 2
 size of `type_and_size("string", 6)' = 6
-'fst:=' [4,5,6] = [4 - 2, 5 - 2, 6 - 2]
+'fst :=' [4,5,6] = [4 - 2, 5 - 2, 6 - 2]
 DCG ^ arg1 = 1
 DCG ^ arg3 ^ arg4 = 3
 updated DCG arg1 = foo(8, 2, foo2(3, 4))
 updated DCG arg3 ^ arg4 = foo(8, 2, foo2(9, 4))
+Map0 ^ det_elem('a') = "a"
+Map ^ det_elem('c') = "c"
Index: tests/hard_coded/typeclasses/record_syntax.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/record_syntax.m,v
retrieving revision 1.2
diff -u -u -r1.2 record_syntax.m
--- tests/hard_coded/typeclasses/record_syntax.m	2000/09/15 05:18:48	1.2
+++ tests/hard_coded/typeclasses/record_syntax.m	2000/12/05 01:34:23
@@ -49,12 +49,12 @@
 
 :- func fst(my_pair(T, U)) = T.
 :- func snd(my_pair(T, U)) = U.
-:- func 'fst:='(my_pair(T, U), V) = my_pair(V, U).
-:- func 'snd:='(my_pair(T, U), V) = my_pair(T, V).
+:- func 'fst :='(my_pair(T, U), V) = my_pair(V, U).
+:- func 'snd :='(my_pair(T, U), V) = my_pair(T, V).
 
 :- implementation.
 
-:- import_module list.
+:- import_module list, map, std_util.
 
 :- type my_pair(T, U) ---> (fst::T) - (snd::U).
 
@@ -97,20 +97,25 @@
 
 	% Test taking the address of an update function
 	% for which a mode declaration has been supplied.
-	{ Pairs = list__map('fst:='(Pair), [4, 5, 6]) },
-	write_arg("'fst:=' [4,5,6]", Pairs),
+	{ Pairs = list__map('fst :='(Pair), [4, 5, 6]) },
+	write_arg("'fst :=' [4,5,6]", Pairs),
 
 	=(IO0),
 	{ dcg_syntax(IO0, IO, X, _) },
-	:=(IO).
+	:=(IO),
 
+        { Map0 = map__from_assoc_list(['a' - "a", 'b' - "b", 'd' - "D"]) },
+	write_arg("Map0 ^ det_elem('a')", Map0 ^ det_elem('a')),
+	{ Map = Map0 ^ elem('c') := "c" },
+	write_arg("Map ^ det_elem('c')", Map ^ det_elem('c')).
 
+
 :- instance has_size(int) where [
 		func(size/1) is id
 	].
 
 :- instance has_size(string) where [
-		func(size/1) is length_of_string
+		func(size/1) is string__length
 	].
 
 :- instance has_size(char) where [
@@ -121,14 +126,6 @@
 		func(size/1) is data_size
 	].
 
-:- func id(T) = T.
-id(T) = T.
-
-	% XXX this should be in the library.
-:- func length_of_string(string) = int.
-length_of_string(String) = Length :-
-	string__length(String, Length).	
-
 :- pred dcg_syntax(io__state::di, io__state::uo, foo::in, foo::out) is det.
 
 dcg_syntax(IO0, IO) -->
@@ -152,4 +149,6 @@
 	io__write_string(" = "),
 	io__write(Arg),
 	io__nl.
+
+
 
Index: tests/invalid/record_syntax_errors.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/record_syntax_errors.err_exp,v
retrieving revision 1.4
diff -u -u -r1.4 record_syntax_errors.err_exp
--- tests/invalid/record_syntax_errors.err_exp	2000/10/10 06:23:20	1.4
+++ tests/invalid/record_syntax_errors.err_exp	2000/12/04 03:58:39
@@ -24,13 +24,13 @@
 record_syntax_errors.m:016: Error: no clauses for
 record_syntax_errors.m:016:   predicate `record_syntax_errors:dcg_syntax_2/2'.
 record_syntax_errors.m:042: In clause for predicate `record_syntax_errors:construct_exist_cons/1':
-record_syntax_errors.m:042:   error: invalid field update `field2:=/2':
+record_syntax_errors.m:042:   error: invalid field update `field2 :=/2':
 record_syntax_errors.m:005:   existentially quantified type variable `T' occurs
 record_syntax_errors.m:005:   in the types of field `field2' and some other field
 record_syntax_errors.m:005:   in definition of constructor `record_syntax_errors:exist_cons/3 '.
 record_syntax_errors.m:046: In clause for predicate `record_syntax_errors:arg_type_error/1':
-record_syntax_errors.m:046:   in argument 2 of functor `field6:=/2':
-record_syntax_errors.m:046:   in argument 2 of functor `field7:=/2':
+record_syntax_errors.m:046:   in argument 2 of functor `field6 :=/2':
+record_syntax_errors.m:046:   in argument 2 of functor `field7 :=/2':
 record_syntax_errors.m:046:   type error in unification of argument
 record_syntax_errors.m:046:   and constant `"invalid value"'.
 record_syntax_errors.m:046:   argument has type `int',
@@ -49,10 +49,10 @@
 	V_11 :: int
 
 record_syntax_errors.m:050: In clause for predicate `record_syntax_errors:term_type_error/1':
-record_syntax_errors.m:050:   in argument 2 of functor `field6:=/2':
+record_syntax_errors.m:050:   in argument 2 of functor `field6 :=/2':
 record_syntax_errors.m:050:   in unification of argument
-record_syntax_errors.m:050:   and term `'field4:='(V_5, V_4)':
-record_syntax_errors.m:050:   type error in argument(s) of functor `field4:=/2'.
+record_syntax_errors.m:050:   and term `'field4 :='(V_5, V_4)':
+record_syntax_errors.m:050:   type error in argument(s) of functor `field4 :=/2'.
 record_syntax_errors.m:050:   Argument 1 has type `(record_syntax_errors:cons2)',
 record_syntax_errors.m:050:   expected type was `(record_syntax_errors:cons)'.
 record_syntax_errors.m:023: Inferred :- func field8((record_syntax_errors:cons2)) = int.
--------------------------------------------------------------------------
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