diff: mode inference & mostly uniq modes

Fergus Henderson fjh at cs.mu.oz.au
Mon Nov 24 04:07:47 AEDT 1997


Change unique mode analysis (unique_modes.m) so that it does the same
fixpoint analysis that ordinary mode analysis (modes.m) does. 

This is a first step towards mode inference of "mostly-unique" modes.
Unique mode analysis still won't introduce any new modes, but it may
now change the final insts of inferred modes from `unique' to `mostly_unique'.

The next step (not included in this diff) will be to change the handling of
calls in unique_modes.m so that it does introduce new modes.

compiler/modes.m:
	Add an extra WhatToCheck parameter to lots of predicates,
	so they can also be used for checking unique modes.
	Add a few small new bits of code to handle the
	`WhatToCheck = check_unique_modes' case.
	Also change things so that the inferred modes are normally
	printed only after unique mode analysis, with determinism
	annotations attached.

compiler/unique_modes.m:
	Call the routines in modes.m rather than special casing things.
	The checking of goals is still special-cased, since for
	example unique_modes does not do reordering, but the traversal
	of modules and procedures now uses code from modes.m.

compiler/mode_errors.m:
	Add an extra bool parameter to write_mode_inference_messages
	indicating whether or not to print determinism annotations.

tests/valid/Mmakefile:
tests/valid/mostly_uniq_mode_inf.m:
	Test case for the above change.

cvs diff -N compiler/mode_errors.m compiler/modes.m compiler/unique_modes.m tests/valid/Mmakefile tests/valid/mostly_uniq_mode_inf.m
Index: compiler/mode_errors.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mode_errors.m,v
retrieving revision 1.48
diff -u -r1.48 mode_errors.m
--- mode_errors.m	1997/11/23 05:18:24	1.48
+++ mode_errors.m	1997/11/23 16:56:44
@@ -135,11 +135,14 @@
 :- pred mode_context_init(mode_context).
 :- mode mode_context_init(out) is det.
 
-	% write out the inferred `mode' declarations for a list of pred_ids.
+	% Write out the inferred `mode' declarations for a list of pred_ids.
+	% The bool indicates whether or not to write out determinism
+	% annotations on the modes (it should only be set to `yes' _after_
+	% determinism analysis).
 
-:- pred write_mode_inference_messages(list(pred_id), module_info,
+:- pred write_mode_inference_messages(list(pred_id), bool, module_info,
 				io__state, io__state).
-:- mode write_mode_inference_messages(in, in, di, uo) is det.
+:- mode write_mode_inference_messages(in, in, in, di, uo) is det.
 
 	% report an error for the case when two mode declarations
 	% declare indistinguishable modes
@@ -822,47 +825,54 @@
 
 	% write out the inferred `mode' declarations for a list of pred_ids.
 
-write_mode_inference_messages([], _) --> [].
-write_mode_inference_messages([PredId | PredIds], ModuleInfo) -->
+write_mode_inference_messages([], _, _) --> [].
+write_mode_inference_messages([PredId | PredIds], OutputDetism, ModuleInfo) -->
 	{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
 	{ pred_info_get_marker_list(PredInfo, Markers) },
 	( { list__member(request(infer_modes), Markers) } ->
 		{ pred_info_procedures(PredInfo, Procs) },
 		{ map__keys(Procs, ProcIds) },
-		write_mode_inference_messages_2(ProcIds, Procs, PredInfo)
+		write_mode_inference_messages_2(ProcIds, Procs, PredInfo,
+			OutputDetism)
 	;
 		[]
 	),
-	write_mode_inference_messages(PredIds, ModuleInfo).
+	write_mode_inference_messages(PredIds, OutputDetism, ModuleInfo).
 
 	% write out the inferred `mode' declarations for a list of
 	% proc_ids
 
 :- pred write_mode_inference_messages_2(list(proc_id), proc_table, pred_info,
-				io__state, io__state).
-:- mode write_mode_inference_messages_2(in, in, in, di, uo) is det.
+				bool, io__state, io__state).
+:- mode write_mode_inference_messages_2(in, in, in, in, di, uo) is det.
 
-write_mode_inference_messages_2([], _, _) --> [].
-write_mode_inference_messages_2([ProcId | ProcIds], Procs, PredInfo) -->
+write_mode_inference_messages_2([], _, _, _) --> [].
+write_mode_inference_messages_2([ProcId | ProcIds], Procs, PredInfo,
+		OutputDetism) -->
 	{ map__lookup(Procs, ProcId, ProcInfo) },
-	write_mode_inference_message(PredInfo, ProcInfo),
-	write_mode_inference_messages_2(ProcIds, Procs, PredInfo).
+	write_mode_inference_message(PredInfo, ProcInfo, OutputDetism),
+	write_mode_inference_messages_2(ProcIds, Procs, PredInfo, OutputDetism).
 
 	% write out the inferred `mode' declaration
 	% for a single function or predicate.
 
-:- pred write_mode_inference_message(pred_info, proc_info,
+:- pred write_mode_inference_message(pred_info, proc_info, bool,
 				io__state, io__state).
-:- mode write_mode_inference_message(in, in, di, uo) is det.
+:- mode write_mode_inference_message(in, in, in, di, uo) is det.
 
-write_mode_inference_message(PredInfo, ProcInfo) -->
+write_mode_inference_message(PredInfo, ProcInfo, OutputDetism) -->
 	{ pred_info_name(PredInfo, PredName) },
 	{ Name = unqualified(PredName) },
 	{ pred_info_context(PredInfo, Context) },
 	{ proc_info_argmodes(ProcInfo, Modes0) },
 	{ varset__init(VarSet) },
 	{ pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
-	{ MaybeDet = no },
+	( { OutputDetism = yes } ->
+		{ proc_info_inferred_determinism(ProcInfo, Detism) },
+		{ MaybeDet = yes(Detism) }
+	;
+		{ MaybeDet = no }
+	),
 	prog_out__write_context(Context),
 	{ strip_builtin_qualifiers_from_mode_list(Modes0, Modes) },
 	io__write_string("Inferred "),
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.207
diff -u -r1.207 modes.m
--- modes.m	1997/11/23 05:18:27	1.207
+++ modes.m	1997/11/23 16:49:43
@@ -144,11 +144,17 @@
 :- pred modecheck(module_info, module_info, bool, io__state, io__state).
 :- mode modecheck(in, out, out, di, uo) is det.
 
-	% Mode-check the code for single predicate.
-
-:- pred modecheck_pred_mode(pred_id, pred_info, module_info, module_info,
-			int, io__state, io__state).
-:- mode modecheck_pred_mode(in, in, in, out, out, di, uo) is det.
+	% Mode-check or unique-mode-check the code for all the predicates
+	% in a module.
+:- pred check_pred_modes(how_to_check_goal, module_info, module_info, bool,
+				io__state, io__state).
+:- mode check_pred_modes(in, in, out, out, di, uo) is det.
+
+	% Mode-check or unique-mode-check the code for single predicate.
+
+:- pred modecheck_pred_mode(pred_id, pred_info, how_to_check_goal,
+			module_info, module_info, int, io__state, io__state).
+:- mode modecheck_pred_mode(in, in, in, in, out, out, di, uo) is det.
 
 	% Mode-check the code for predicate in a given mode.
 
@@ -156,6 +162,16 @@
 			io__state, io__state).
 :- mode modecheck_proc(in, in, in, out, out, di, uo) is det.
 
+	% Mode-check or unique-mode-check the code for predicate in a
+	% given mode.
+
+:- pred modecheck_proc(proc_id, pred_id, how_to_check_goal,
+			module_info, module_info, int,
+			io__state, io__state).
+:- mode modecheck_proc(in, in, in, in, out, out, di, uo) is det.
+
+	% Mode-check the code for predicate in a given mode.
+
 :- pred modecheck_proc_info(proc_id, pred_id, module_info, proc_info,
 		module_info, proc_info, int, io__state, io__state).
 :- mode modecheck_proc_info(in, in, in, in, out, out, out, di, uo) is det.
@@ -289,7 +305,7 @@
 	io__set_output_stream(StdErr, OldStream),
 
 	maybe_write_string(Verbose, "% Mode-checking clauses...\n"),
-	check_pred_modes(Module0, Module, UnsafeToContinue),
+	check_pred_modes(check_modes, Module0, Module, UnsafeToContinue),
 	maybe_report_stats(Statistics),
 
 	io__set_output_stream(OldStream, _).
@@ -298,29 +314,39 @@
 	
 	% Mode-check the code for all the predicates in a module.
 
-:- pred check_pred_modes(module_info, module_info, bool, io__state, io__state).
-:- mode check_pred_modes(in, out, out, di, uo) is det.
-
-check_pred_modes(ModuleInfo0, ModuleInfo, UnsafeToContinue) -->
+check_pred_modes(WhatToCheck, ModuleInfo0, ModuleInfo, UnsafeToContinue) -->
 	{ module_info_predids(ModuleInfo0, PredIds) },
 	globals__io_lookup_int_option(mode_inference_iteration_limit,
 		MaxIterations),
-	modecheck_to_fixpoint(PredIds, MaxIterations, ModuleInfo0,
+	modecheck_to_fixpoint(PredIds, MaxIterations, WhatToCheck, ModuleInfo0,
 					ModuleInfo1, UnsafeToContinue),
-	write_mode_inference_messages(PredIds, ModuleInfo1),
+	( { WhatToCheck = check_unique_modes },
+		write_mode_inference_messages(PredIds, yes, ModuleInfo1)
+	; { WhatToCheck = check_modes },
+		( { UnsafeToContinue = yes } ->
+			write_mode_inference_messages(PredIds, no, ModuleInfo1)
+		;
+			[]
+		)
+	),
 	modecheck_unify_procs(check_modes, ModuleInfo1, ModuleInfo).
 
 	% Iterate over the list of pred_ids in a module.
 
-:- pred modecheck_to_fixpoint(list(pred_id), int, module_info, 
-			module_info, bool, io__state, io__state).
-:- mode modecheck_to_fixpoint(in, in, in, out, out, di, uo) is det.
+:- pred modecheck_to_fixpoint(list(pred_id), int, how_to_check_goal,
+			module_info, module_info, bool, io__state, io__state).
+:- mode modecheck_to_fixpoint(in, in, in, in, out, out, di, uo) is det.
 
-modecheck_to_fixpoint(PredIds, MaxIterations, ModuleInfo0,
+modecheck_to_fixpoint(PredIds, MaxIterations, WhatToCheck, ModuleInfo0,
 		ModuleInfo, UnsafeToContinue) -->
-	{ copy_module_clauses_to_procs(PredIds, ModuleInfo0, ModuleInfo1) },
-	modecheck_pred_modes_2(PredIds, ModuleInfo1, ModuleInfo2, no, Changed,
-				0, NumErrors),
+	( { WhatToCheck = check_modes } ->
+		{ copy_module_clauses_to_procs(PredIds, ModuleInfo0,
+			ModuleInfo1) }
+	;
+		{ ModuleInfo1 = ModuleInfo0 }
+	),
+	modecheck_pred_modes_2(PredIds, WhatToCheck, ModuleInfo1, ModuleInfo2,
+				no, Changed, 0, NumErrors),
 	% stop if we have reached a fixpoint or found any errors
 	( { Changed = no ; NumErrors > 0 } ->
 		{ ModuleInfo = ModuleInfo2 },
@@ -334,14 +360,15 @@
 		;
 			globals__io_lookup_bool_option(debug_modes, DebugModes),
 			( { DebugModes = yes } ->
-				write_mode_inference_messages(PredIds,
+				write_mode_inference_messages(PredIds, no,
 						ModuleInfo2)
 			;
 				[]
 			),
 			{ MaxIterations1 is MaxIterations - 1 },
 			modecheck_to_fixpoint(PredIds, MaxIterations1,
-				ModuleInfo2, ModuleInfo, UnsafeToContinue)
+				WhatToCheck, ModuleInfo2,
+				ModuleInfo, UnsafeToContinue)
 		)
 	).
 
@@ -360,14 +387,15 @@
 	io__format("(The current limit is %d iterations.)\n",
 		[i(MaxIterations)]).
 
-:- pred modecheck_pred_modes_2(list(pred_id), module_info, module_info,
-			bool, bool, int, int, io__state, io__state).
-:- mode modecheck_pred_modes_2(in, in, out,
-			in, out, in, out, di, uo) is det.
+:- pred modecheck_pred_modes_2(list(pred_id), how_to_check_goal,
+			module_info, module_info, bool, bool, int, int,
+			io__state, io__state).
+:- mode modecheck_pred_modes_2(in, in, in, out, in, out, in, out, di, uo)
+			is det.
 
-modecheck_pred_modes_2([], ModuleInfo, ModuleInfo, Changed, Changed,
+modecheck_pred_modes_2([], _, ModuleInfo, ModuleInfo, Changed, Changed,
 		NumErrors, NumErrors) --> [].
-modecheck_pred_modes_2([PredId | PredIds], ModuleInfo0, ModuleInfo,
+modecheck_pred_modes_2([PredId | PredIds], WhatToCheck, ModuleInfo0, ModuleInfo,
 		Changed0, Changed, NumErrors0, NumErrors) -->
 	{ module_info_preds(ModuleInfo0, Preds0) },
 	{ map__lookup(Preds0, PredId, PredInfo0) },
@@ -380,16 +408,11 @@
 		{ Changed1 = Changed0 },
 		{ NumErrors1 = NumErrors0 }
 	;
-		{ pred_info_get_marker_list(PredInfo0, Markers) },
-		( { list__member(request(infer_modes), Markers) } ->
-			write_pred_progress_message("% Mode-analysing ",
-				PredId, ModuleInfo0)
-		;
-			write_pred_progress_message("% Mode-checking ",
-				PredId, ModuleInfo0)
-		),
-		modecheck_pred_mode_2(PredId, PredInfo0, ModuleInfo0,
-			ModuleInfo1, Changed0, Changed1, ErrsInThisPred),
+		write_modes_progress_message(PredId, PredInfo0, ModuleInfo0,
+			WhatToCheck),
+		modecheck_pred_mode_2(PredId, PredInfo0, WhatToCheck,
+			ModuleInfo0, ModuleInfo1, Changed0, Changed1,
+			ErrsInThisPred),
 		{ ErrsInThisPred = 0 ->
 			ModuleInfo3 = ModuleInfo1
 		;
@@ -402,55 +425,90 @@
 		},
 		{ NumErrors1 is NumErrors0 + ErrsInThisPred }
 	),
-	modecheck_pred_modes_2(PredIds, ModuleInfo3, ModuleInfo,
+	modecheck_pred_modes_2(PredIds, WhatToCheck, ModuleInfo3, ModuleInfo,
 		Changed1, Changed, NumErrors1, NumErrors).
 
+:- pred write_modes_progress_message(pred_id, pred_info, module_info,
+			how_to_check_goal, io__state, io__state).
+:- mode write_modes_progress_message(in, in, in, in, di, uo) is det.
+	
+write_modes_progress_message(PredId, PredInfo, ModuleInfo, WhatToCheck) -->
+	% { pred_info_get_markers(PredInfo, Markers) },
+	% ( { check_marker(Markers, infer_modes) } ->
+	{ pred_info_get_marker_list(PredInfo, Markers) },
+	( { list__member(request(infer_modes), Markers) } ->
+		(	{ WhatToCheck = check_modes },
+			write_pred_progress_message("% Mode-analysing ",
+				PredId, ModuleInfo)
+		;	{ WhatToCheck = check_unique_modes },
+			write_pred_progress_message("% Unique-mode-analysing ",
+				PredId, ModuleInfo)
+		)
+	;
+		(	{ WhatToCheck = check_modes },
+			write_pred_progress_message("% Mode-checking ",
+				PredId, ModuleInfo)
+		;	{ WhatToCheck = check_unique_modes },
+			write_pred_progress_message("% Unique-mode-checking ",
+				PredId, ModuleInfo)
+		)
+	).
+
 %-----------------------------------------------------------------------------%
 
 	% Mode-check the code for single predicate.
 
-modecheck_pred_mode(PredId, PredInfo0, ModuleInfo0, ModuleInfo, NumErrors) -->
-	modecheck_pred_mode_2(PredId, PredInfo0, ModuleInfo0, ModuleInfo,
-		no, _Changed, NumErrors).
-
-:- pred modecheck_pred_mode_2(pred_id, pred_info, module_info, module_info,
-			bool, bool, int, io__state, io__state).
-:- mode modecheck_pred_mode_2(in, in, in, out, in, out, out, di, uo) is det.
+modecheck_pred_mode(PredId, PredInfo0, WhatToCheck, ModuleInfo0,
+		ModuleInfo, NumErrors) -->
+	modecheck_pred_mode_2(PredId, PredInfo0, WhatToCheck,
+		ModuleInfo0, ModuleInfo, no, _Changed, NumErrors).
+
+:- pred modecheck_pred_mode_2(pred_id, pred_info, how_to_check_goal,
+			module_info, module_info, bool, bool, int,
+			io__state, io__state).
+:- mode modecheck_pred_mode_2(in, in, in, in, out, in, out, out, di, uo) is det.
 
-modecheck_pred_mode_2(PredId, PredInfo0, ModuleInfo0, ModuleInfo,
+modecheck_pred_mode_2(PredId, PredInfo0, WhatToCheck, ModuleInfo0, ModuleInfo,
 		Changed0, Changed, NumErrors) -->
 	{ pred_info_procedures(PredInfo0, Procs0) },
 	{ map__keys(Procs0, ProcIds) },
-	( { ProcIds = [] } ->
-		maybe_report_error_no_modes(PredId, PredInfo0, ModuleInfo0),
-		{ ModuleInfo = ModuleInfo0 },
-		{ NumErrors = 0 },
-		{ Changed = Changed0 }
+	( { WhatToCheck = check_modes } ->
+		( { ProcIds = [] } ->
+			maybe_report_error_no_modes(PredId, PredInfo0,
+					ModuleInfo0),
+			{ NumErrors0 = 0 }
+		;
+			check_for_indistinguishable_modes(ProcIds, PredId,
+				PredInfo0, ModuleInfo0, 0, NumErrors0)
+		)
 	;
-		check_for_indistinguishable_modes(ProcIds, PredId, PredInfo0,
-					ModuleInfo0, 0, NumErrors0),
-		modecheck_procs(ProcIds, PredId, ModuleInfo0, Changed0, 0,
-					ModuleInfo, Changed, NumErrors1),
-		{ NumErrors is NumErrors0 + NumErrors1 }
-	).
+		{ NumErrors0 = 0 }
+	),
+	modecheck_procs(ProcIds, PredId, WhatToCheck,
+				ModuleInfo0, Changed0, NumErrors0,
+				ModuleInfo, Changed, NumErrors).
 
 	% Iterate over the list of modes for a predicate.
 
-:- pred modecheck_procs(list(proc_id), pred_id, module_info, bool, int,
+:- pred modecheck_procs(list(proc_id), pred_id, how_to_check_goal,
+				module_info, bool, int,
 				module_info, bool, int, io__state, io__state).
-:- mode modecheck_procs(in, in, in, in, in, out, out, out, di, uo) is det.
+:- mode modecheck_procs(in, in, in, in, in, in, out, out, out, di, uo) is det.
 
-modecheck_procs([], _PredId,  ModuleInfo, Changed, Errs,
+modecheck_procs([], _PredId,  _, ModuleInfo, Changed, Errs,
 				ModuleInfo, Changed, Errs) --> [].
-modecheck_procs([ProcId|ProcIds], PredId, ModuleInfo0, Changed0, Errs0,
+modecheck_procs([ProcId|ProcIds], PredId, WhatToCheck,
+				ModuleInfo0, Changed0, Errs0,
 				ModuleInfo, Changed, Errs) -->
 	% mode-check that mode of the predicate
-	modecheck_proc_2(ProcId, PredId, ModuleInfo0, Changed0,
+	modecheck_proc_2(ProcId, PredId, WhatToCheck,
+				ModuleInfo0, Changed0,
 				ModuleInfo1, Changed1, NumErrors),
 	{ Errs1 is Errs0 + NumErrors },
 		% recursively process the remaining modes
-	modecheck_procs(ProcIds, PredId, ModuleInfo1, Changed1,
-			Errs1, ModuleInfo, Changed, Errs).
+	modecheck_procs(ProcIds, PredId, WhatToCheck,
+				ModuleInfo1, Changed1, Errs1,
+				ModuleInfo, Changed, Errs).
 
 %-----------------------------------------------------------------------------%
 
@@ -503,16 +561,22 @@
 	% Mode-check the code for predicate in a given mode.
 
 modecheck_proc(ProcId, PredId, ModuleInfo0, ModuleInfo, NumErrors) -->
-	modecheck_proc_2(ProcId, PredId, ModuleInfo0, no,
+	modecheck_proc(ProcId, PredId, check_modes,
+		ModuleInfo0, ModuleInfo, NumErrors).
+
+modecheck_proc(ProcId, PredId, WhatToCheck, ModuleInfo0,
+			ModuleInfo, NumErrors) -->
+	modecheck_proc_2(ProcId, PredId, WhatToCheck, ModuleInfo0, no,
 			ModuleInfo, _Changed, NumErrors).
 
-:- pred modecheck_proc_2(proc_id, pred_id, module_info, bool, 
-			module_info, bool, int,
+:- pred modecheck_proc_2(proc_id, pred_id, how_to_check_goal,
+			module_info, bool, module_info, bool, int,
 			io__state, io__state).
-:- mode modecheck_proc_2(in, in, in, in, out, out, out, di, uo) is det.
+:- mode modecheck_proc_2(in, in, in, in, in, out, out, out, di, uo) is det.
 
-modecheck_proc_2(ProcId, PredId, ModuleInfo0, Changed0,
-				ModuleInfo, Changed, NumErrors) -->
+modecheck_proc_2(ProcId, PredId, WhatToCheck,
+			ModuleInfo0, Changed0,
+			ModuleInfo, Changed, NumErrors) -->
 		% get the proc_info from the module_info
 	{ module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
 					_PredInfo0, ProcInfo0) },
@@ -522,7 +586,7 @@
 		{ NumErrors = 0 }
 	;
 			% modecheck it
-		modecheck_proc_3(ProcId, PredId,
+		modecheck_proc_3(ProcId, PredId, WhatToCheck,
 				ModuleInfo0, ProcInfo0, Changed0,
 				ModuleInfo1, ProcInfo, Changed, NumErrors),
 			% save the proc_info back in the module_info
@@ -537,18 +601,22 @@
 
 modecheck_proc_info(ProcId, PredId, ModuleInfo0, ProcInfo0,
 		ModuleInfo, ProcInfo, NumErrors) -->
-	modecheck_proc_3(ProcId, PredId, ModuleInfo0, ProcInfo0, no,
-		ModuleInfo, ProcInfo, _Changed, NumErrors).
+	{ WhatToCheck = check_modes },
+	modecheck_proc_3(ProcId, PredId, WhatToCheck,
+			ModuleInfo0, ProcInfo0, no,
+			ModuleInfo, ProcInfo, _Changed, NumErrors).
 
-:- pred modecheck_proc_3(proc_id, pred_id, module_info, proc_info, bool,
+:- pred modecheck_proc_3(proc_id, pred_id, how_to_check_goal,
+			module_info, proc_info, bool,
 			module_info, proc_info, bool, int,
 			io__state, io__state).
-:- mode modecheck_proc_3(in, in, in, in, in, out, out, out, out, di, uo)
+:- mode modecheck_proc_3(in, in, in, in, in, in, out, out, out, out, di, uo)
 	is det.
 
-modecheck_proc_3(ProcId, PredId, ModuleInfo0, ProcInfo0, Changed0,
-				ModuleInfo, ProcInfo, Changed, NumErrors,
-				IOState0, IOState) :-
+modecheck_proc_3(ProcId, PredId, WhatToCheck,
+			ModuleInfo0, ProcInfo0, Changed0,
+			ModuleInfo, ProcInfo, Changed, NumErrors,
+			IOState0, IOState) :-
 		% extract the useful fields in the proc_info
 	proc_info_headvars(ProcInfo0, HeadVars),
 	proc_info_argmodes(ProcInfo0, ArgModes0),
@@ -567,21 +635,38 @@
 		proc_info_context(ProcInfo0, Context)
 	),
 
-		% modecheck the clause - first set the initial instantiation
-		% of the head arguments, mode-check the body, and
-		% then check that the final instantiation matches that in
-		% the mode declaration
+	%
+	% modecheck the clause - first set the initial instantiation
+	% of the head arguments, mode-check the body, and
+	% then check that the final instantiation matches that in
+	% the mode declaration
+	%
+
+		% construct the initial instmap
 	mode_list_get_initial_insts(ArgModes0, ModuleInfo0, ArgInitialInsts),
 	assoc_list__from_corresponding_lists(HeadVars, ArgInitialInsts, InstAL),
 	instmap__from_assoc_list(InstAL, InstMap0),
+
+		% construct the initial set of live vars:
 		% initially, only the non-clobbered head variables are live
-	mode_list_get_final_insts(ArgModes0, ModuleInfo0, ArgFinalInsts0),
 	get_live_vars(HeadVars, ArgLives0, LiveVarsList),
 	set__list_to_set(LiveVarsList, LiveVars),
+
+		% initialize the mode info
 	mode_info_init(IOState0, ModuleInfo0, PredId, ProcId,
 			Context, LiveVars, InstMap0, ModeInfo0),
 	mode_info_set_changed_flag(Changed0, ModeInfo0, ModeInfo1),
-	modecheck_goal(Body0, Body, ModeInfo1, ModeInfo2),
+
+		% modecheck the procedure body
+	( WhatToCheck = check_unique_modes ->
+		unique_modes__check_goal(Body0, Body, ModeInfo1, ModeInfo2)
+	;
+		modecheck_goal(Body0, Body, ModeInfo1, ModeInfo2)
+	),
+
+		% check that final insts match those specified in the
+		% mode declaration
+	mode_list_get_final_insts(ArgModes0, ModuleInfo0, ArgFinalInsts0),
 	pred_info_get_marker_list(PredInfo, Markers),
 	( list__member(request(infer_modes), Markers) ->
 		InferModes = yes
@@ -590,8 +675,10 @@
 	),
 	modecheck_final_insts_2(HeadVars, ArgFinalInsts0, ModeInfo2,
 			InferModes, ArgFinalInsts, ModeInfo3),
-	inst_lists_to_mode_list(ArgInitialInsts, ArgFinalInsts, ArgModes),
+
+		% report any errors we found, and save away the results
 	report_mode_errors(ModeInfo3, ModeInfo),
+	inst_lists_to_mode_list(ArgInitialInsts, ArgFinalInsts, ArgModes),
 	mode_info_get_changed_flag(ModeInfo, Changed),
 	mode_info_get_module_info(ModeInfo, ModuleInfo),
 	mode_info_get_num_errors(ModeInfo, NumErrors),
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.40
diff -u -r1.40 unique_modes.m
--- unique_modes.m	1997/09/15 21:12:50	1.40
+++ unique_modes.m	1997/11/23 16:01:54
@@ -62,146 +62,18 @@
 
 %-----------------------------------------------------------------------------%
 
-	% This section just traverses the module structure.
-
 unique_modes__check_module(ModuleInfo0, ModuleInfo) -->
-	{ module_info_predids(ModuleInfo0, PredIds) },
-	unique_modes__check_preds(PredIds, ModuleInfo0, ModuleInfo1),
-	modecheck_unify_procs(check_unique_modes, ModuleInfo1, ModuleInfo).
-
-:- pred unique_modes__check_preds(list(pred_id), module_info, module_info,
-					io__state, io__state).
-:- mode unique_modes__check_preds(in, in, out, di, uo) is det.
-
-unique_modes__check_preds([], ModuleInfo, ModuleInfo) --> [].
-unique_modes__check_preds([PredId | PredIds], ModuleInfo0, ModuleInfo) -->
-	{ module_info_preds(ModuleInfo0, PredTable) },
-	{ map__lookup(PredTable, PredId, PredInfo) },
-	{ pred_info_non_imported_procids(PredInfo, ProcIds) },
-	( { ProcIds \= [] } ->
-		write_pred_progress_message("% Unique-mode-checking ",
-			PredId, ModuleInfo0)
-	;
-		[]
-	),
-	unique_modes__check_procs(ProcIds, PredId, ModuleInfo0, ModuleInfo1),
-	unique_modes__check_preds(PredIds, ModuleInfo1, ModuleInfo).
-
-:- pred unique_modes__check_procs(list(proc_id), pred_id,
-					module_info, module_info,
-					io__state, io__state).
-:- mode unique_modes__check_procs(in, in, in, out, di, uo) is det.
-
-unique_modes__check_procs([], _PredId, ModuleInfo, ModuleInfo) --> [].
-unique_modes__check_procs([ProcId | ProcIds], PredId, ModuleInfo0,
-		ModuleInfo) -->
-	unique_modes__check_proc(ProcId, PredId, ModuleInfo0, ModuleInfo1),
-	unique_modes__check_procs(ProcIds, PredId, ModuleInfo1, ModuleInfo).
+	check_pred_modes(check_unique_modes, ModuleInfo0, ModuleInfo,
+			_UnsafeToContinue).
 
 unique_modes__check_proc(ProcId, PredId, ModuleInfo0, ModuleInfo) -->
-	{ module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
-		_PredInfo0, ProcInfo0) },
-	( { proc_info_can_process(ProcInfo0, no) } ->
-		{ ModuleInfo = ModuleInfo0 }
+	modecheck_proc(ProcId, PredId, check_unique_modes,
+		ModuleInfo0, ModuleInfo, NumErrors),
+	( { NumErrors \= 0 } ->
+		io__set_exit_status(1)
 	;
-		unique_modes__check_proc_2(ProcInfo0, PredId, ProcId,
-			ModuleInfo0, ProcInfo, ModuleInfo1),
-
-		{ module_info_preds(ModuleInfo1, PredTable1) },
-		{ map__lookup(PredTable1, PredId, PredInfo1) },
-		{ pred_info_procedures(PredInfo1, ProcTable1) },
-		{ map__set(ProcTable1, ProcId, ProcInfo, ProcTable) },
-		{ pred_info_set_procedures(PredInfo1, ProcTable, PredInfo) },
-		{ map__set(PredTable1, PredId, PredInfo, PredTable) },
-		{ module_info_set_preds(ModuleInfo1, PredTable, ModuleInfo) }
+		[]
 	).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-	% just check a single procedure
-:- pred unique_modes__check_proc_2(proc_info, pred_id, proc_id, module_info,
-				proc_info, module_info, io__state, io__state).
-:- mode unique_modes__check_proc_2(in, in, in, in, out, out, di, uo) is det.
-
-unique_modes__check_proc_2(ProcInfo0, PredId, ProcId, ModuleInfo0,
-			ProcInfo, ModuleInfo,
-			IOState0, IOState) :-
-	%
-	% Extract the useful fields in the proc_info.
-	%
-	proc_info_headvars(ProcInfo0, Args),
-	proc_info_argmodes(ProcInfo0, ArgModes),
-	proc_info_arglives(ProcInfo0, ModuleInfo0, ArgLives),
-	proc_info_goal(ProcInfo0, Goal0),
-
-	%
-	% Figure out the right context to use.
-	% We use the context of the first clause, unless
-	% there weren't any clauses at all, in which case
-	% we use the context of the mode declaration.
-	%
-	module_info_pred_info(ModuleInfo0, PredId, PredInfo),
-	pred_info_clauses_info(PredInfo, ClausesInfo),
-	ClausesInfo = clauses_info(_, _, _, _, ClauseList),
-	( ClauseList = [FirstClause | _] ->
-		FirstClause = clause(_, _, Context)
-	;
-		proc_info_context(ProcInfo0, Context)
-	),
-
-	%
-	% Construct the initial instmap
-	%
-	mode_list_get_initial_insts(ArgModes, ModuleInfo0, ArgInitialInsts),
-	assoc_list__from_corresponding_lists(Args, ArgInitialInsts, InstAL),
-	instmap__from_assoc_list(InstAL, InstMap0),
-
-	%
-	% Construct the initial set of live variables:
-	% initially, only the non-clobbered head variables are live
-	%
-	get_live_vars(Args, ArgLives, LiveVarsList),
-	set__list_to_set(LiveVarsList, LiveVars),
-
-	%
-	% At last we're ready to construct the initial mode_info
-	%
-	mode_info_init(IOState0, ModuleInfo0, PredId, ProcId, Context,
-			LiveVars, InstMap0, ModeInfo0),
-	%
-	% Modecheck the goal
-	%
-	unique_modes__check_goal(Goal0, Goal, ModeInfo0, ModeInfo1),
-
-	%
-	% Check that the final insts of the head vars is OK
-	%
-	mode_list_get_final_insts(ArgModes, ModuleInfo0, ArgFinalInsts),
-	modecheck_final_insts(Args, ArgFinalInsts, ModeInfo1, ModeInfo2),
-
-	%
-	% If we encountered any errors then report them
-	%
-	report_mode_errors(ModeInfo2, ModeInfo),
-
-	%
-	% Get the info we need from the mode_info and stuff it back
-	% in the proc_info
-	%
-	mode_info_get_module_info(ModeInfo, ModuleInfo),
-	mode_info_get_io_state(ModeInfo, IOState1),
-	mode_info_get_errors(ModeInfo, Errors),
-	( Errors = [] ->
-		IOState = IOState1
-	;
-		io__set_exit_status(1, IOState1, IOState)
-	),
-	mode_info_get_varset(ModeInfo, VarSet),
-	mode_info_get_var_types(ModeInfo, VarTypes),
-	proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
-	proc_info_set_variables(ProcInfo1, VarSet, ProcInfo2),
-	proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo).
 
 	% XXX we currently make the conservative assumption that
 	% any non-local variable in a disjunction or nondet call
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.3
diff -u -r1.3 Mmakefile
--- Mmakefile	1997/11/22 17:14:02	1.3
+++ Mmakefile	1997/11/23 16:32:41
@@ -55,6 +55,7 @@
 	loop_in_disj.m \
 	middle_rec_labels.m \
 	modes_bug.m \
+	mostly_uniq_mode_inf.m \
 	multidet_prune1.m \
 	multidet_test.m \
 	nasty_func_test.m \
@@ -105,6 +106,7 @@
 MCFLAGS-higher_order_implied_mode = -O-1
 MCFLAGS-livevals_seq		= -O5 --opt-space
 MCFLAGS-middle_rec_labels	= --middle-rec --no-follow-vars 
+MCFLAGS-mostly_uniq_mode_inf	= --infer-all
 MCFLAGS-pred_with_no_modes	= --infer-all
 MCFLAGS-simplify_bug		= -O-1
 MCFLAGS-two_way_unif		= -O-1
Index: tests/valid/mostly_uniq_mode_inf.m
===================================================================
RCS file: mostly_uniq_mode_inf.m
diff -N mostly_uniq_mode_inf.m
--- /dev/null	Mon Nov 24 03:56:44 1997
+++ mostly_uniq_mode_inf.m	Mon Nov 24 03:15:58 1997
@@ -0,0 +1,20 @@
+% This module tests inference of mostly-unique modes.
+% The compiler needs to infer mostly-unique modes for foo/2 and foo2/2.
+
+:- module mostly_uniq_mode_inf.
+:- interface.
+:- pred p is semidet.
+
+:- implementation.
+:- import_module int.
+
+p :- foo(42, Z), bar(Z, A), A > 100.
+
+foo(X, Y) :- foo2(X, Y).
+
+foo2(X, Y) :- Y is X + 10.
+foo2(X, Y) :- Y = X.
+
+:- mode bar(mdi, muo) is det.
+bar(X, X).
+

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list