[m-rev.] diff: find all reasons for recompilation

Simon Taylor stayl at cs.mu.OZ.AU
Sat Feb 23 18:31:27 AEDT 2002


Estimated hours taken: 2.5
Branches: main

Add an option `--find-all-recompilation-reasons' which causes
smart recompilation to find all reasons why a module needs to
be recompiled, not just the first. This allows test cases in
tests/recompilation to contain multiple tests. Also,
tests/recompilation will now work with deep profiling.

compiler/options.m:
compiler/handle_options.m:
doc/user_guide.texi:
	Add the new option

compiler/recompilation_check.m:
	Collect all reasons for recompilation if
	`--find-all-recompilation-reasons' is set.

tests/recompilation/Mmakefile:
	Add `--find-all-recompilation-reasons' to EXTRA_MCFLAGS.

tests/recompilation/remove_type_re.err_exp.2:
	Update expected output.

Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.133
diff -u -u -r1.133 handle_options.m
--- compiler/handle_options.m	22 Feb 2002 01:51:08 -0000	1.133
+++ compiler/handle_options.m	22 Feb 2002 14:56:09 -0000
@@ -431,6 +431,8 @@
 
 	option_implies(smart_recompilation, generate_item_version_numbers,
 			bool(yes)),
+	option_implies(find_all_recompilation_reasons, verbose_recompilation,
+			bool(yes)),
 	
 	%
 	% Disable `--smart-recompilation' for compilation options
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.356
diff -u -u -r1.356 options.m
--- compiler/options.m	20 Feb 2002 03:14:15 -0000	1.356
+++ compiler/options.m	22 Feb 2002 15:31:03 -0000
@@ -77,6 +77,7 @@
 		;	very_verbose
 		;	verbose_errors
 		;	verbose_recompilation
+		;	find_all_recompilation_reasons
 		;	verbose_make
 		;	statistics
 		;	debug_types
@@ -577,6 +578,8 @@
 	very_verbose		-	bool(no),
 	verbose_errors		-	bool(no),
 	verbose_recompilation	-	bool(no),
+	find_all_recompilation_reasons -
+					bool(no),
 	verbose_make		-	bool(yes),
 	statistics		-	bool(no),
 	debug_types		- 	bool(no),
@@ -1047,6 +1050,8 @@
 long_option("very-verbose",		very_verbose).
 long_option("verbose-error-messages",	verbose_errors).
 long_option("verbose-recompilation",	verbose_recompilation).
+long_option("find-all-recompilation-reasons",
+					find_all_recompilation_reasons).
 long_option("verbose-make",		verbose_make).
 long_option("statistics",		statistics).
 long_option("debug-types",		debug_types).
@@ -1958,8 +1963,11 @@
 %		"\tOutput progress messages about the progress of the",
 %		"\t`--make' option.",
 		"--verbose-recompilation",
-		"\tWhen using `--smart-recompilation', output messages\n",
+		"\tWhen using `--smart-recompilation', output messages",
 		"\texplaining why a module needs to be recompiled.",
+		"--find-all-recompilation-reasons",
+		"\tFind all the reasons why a module needs to be recompiled,",
+		"\tnot just the first.  Implies `--verbose-recompilation'.",
 		"-S, --statistics",
 		"\tOutput messages about the compiler's time/space usage.",
 		"\tAt the moment this option implies `--no-trad-passes', so you get",
Index: compiler/recompilation_check.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/recompilation_check.m,v
retrieving revision 1.7
diff -u -u -r1.7 recompilation_check.m
--- compiler/recompilation_check.m	8 Feb 2002 02:26:58 -0000	1.7
+++ compiler/recompilation_check.m	23 Feb 2002 05:57:10 -0000
@@ -67,9 +67,11 @@
 recompilation_check__should_recompile(ModuleName, FindTargetFiles,
 		FindTimestampFiles, Info ^ modules_to_recompile,
 		Info ^ read_modules) -->
+	globals__io_lookup_bool_option(find_all_recompilation_reasons,
+			FindAll),
 	{ Info0 = recompilation_check_info(ModuleName, no, [], map__init,
 			init_item_id_set(map__init, map__init, map__init),
-			set__init, some([])) },
+			set__init, some([]), FindAll, []) },
 	recompilation_check__should_recompile_2(no, FindTargetFiles,
 		FindTimestampFiles, ModuleName, Info0, Info).
 	
@@ -100,15 +102,8 @@
 		    ),
 		    Result),
 		(
-			{ Result = succeeded(Info4) },
-			FindTimestampFiles(ModuleName, TimestampFiles),
-			list__foldl(touch_datestamp, TimestampFiles),
-			write_recompilation_message(
-			    (pred(di, uo) is det -->
-				io__write_string("Not recompiling module "),
-				prog_out__write_sym_name(ModuleName),
-				io__write_string(".\n")
-			    ))
+			{ Result = succeeded(Info3) },
+			{ Reasons = Info3 ^ recompilation_reasons }
 		;
 			{ Result = failed },
 			{ error("recompilation_check__should_recompile_2") }
@@ -121,13 +116,28 @@
 			},
 			{ RecompileException =
 				recompile_exception(Reason, Info3) },
+			{ Reasons = [Reason] }
+		),
+
+		( { Reasons = [] } ->
+			FindTimestampFiles(ModuleName, TimestampFiles),
 			write_recompilation_message(
 			    (pred(di, uo) is det -->
-				write_recompile_reason(ModuleName, Reason)
+				io__write_string("Not recompiling module "),
+				prog_out__write_sym_name(ModuleName),
+				io__write_string(".\n")
 			    )),
-			{ add_module_to_recompile(ModuleName, Info3, Info4) }
+			list__foldl(touch_datestamp, TimestampFiles),
+			{ Info4 = Info3 }
+		;
+			{ add_module_to_recompile(ModuleName, Info3, Info4) },
+			write_recompilation_message(
+			    (pred(di, uo) is det -->
+				list__foldl(
+					write_recompile_reason(ModuleName),
+					list__reverse(Reasons))
+			    ))
 		),
-
 		io__set_input_stream(OldInputStream, VersionStream),
 		io__close_input(VersionStream),
 
@@ -207,7 +217,7 @@
 		% For inline sub-modules we don't need to check
 		% the module timestamp because we've already checked
 		% the timestamp for the parent module.
-		[]
+		{ Info3 = Info0 }
 	;
 		%
 		% If the module has changed, recompile.
@@ -222,11 +232,10 @@
 		->
 			record_read_file(ModuleName,
 				ModuleTimestamp ^ timestamp := NewTimestamp,
-				Items, Error, FileName, Info0, RecompileInfo0),
-			RecompileInfo =
-				RecompileInfo0 ^ modules_to_recompile := (all),
-			throw(recompile_exception(module_changed(FileName),
-					RecompileInfo))
+				Items, Error, FileName, Info0, Info1),
+			Info2 = Info1 ^ modules_to_recompile := (all),
+			record_recompilation_reason(module_changed(FileName),
+				Info2, Info3)	
 		;
 			( Error \= no_module_errors
 			; MaybeNewTimestamp = no
@@ -238,14 +247,14 @@
 				    ++ FileName ++ "'."),
 				Info0)
 		;
-			true
+			Info3 = Info0
 		}
 	),
 
 	%
 	% Find out whether this module has any inline sub-modules.
 	%
-	read_term_check_for_error_or_eof(Info0, "inline sub-modules",
+	read_term_check_for_error_or_eof(Info3, "inline sub-modules",
 		SubModulesTerm),
 	{ 
 		SubModulesTerm = term__functor(term__atom("sub_modules"),
@@ -256,44 +265,44 @@
 			),
 			SubModuleTerms, SubModules)
 	->
-		Info1 = Info0 ^ sub_modules := SubModules
+		Info4 = Info3 ^ sub_modules := SubModules
 	;
 		Reason1 = syntax_error(get_term_context(SubModulesTerm),
 				"error in sub_modules term"),
-		throw_syntax_error(Reason1, Info0)
+		throw_syntax_error(Reason1, Info3)
 	},
 
 	%
 	% Check whether the output files are present and up-to-date.
 	%
-	FindTargetFiles(Info1 ^ module_name, TargetFiles),
-	list__foldl(
-	    (pred(TargetFile::in, di, uo) is det -->
+	FindTargetFiles(Info4 ^ module_name, TargetFiles),
+	list__foldl2(
+	    (pred(TargetFile::in, RInfo0::in, RInfo::out, di, uo) is det -->
 		io__file_modification_time(TargetFile, TargetModTimeResult),
-		(
-			{ TargetModTimeResult = ok(TargetModTime) },
-			{ compare(TargetModTimeCompare,
+		{
+			TargetModTimeResult = ok(TargetModTime),
+			compare(TargetModTimeCompare,
 				time_t_to_timestamp(TargetModTime),
-				RecordedTimestamp) },
-			{ TargetModTimeCompare = (>) }
+				RecordedTimestamp),
+			TargetModTimeCompare = (>)
 		->
-			[]
+			RInfo = RInfo0
 		;
-			{ Reason2 = output_file_not_up_to_date(TargetFile) },
-			{ throw(recompile_exception(Reason2, Info1)) }
-		)
-	    ), TargetFiles),
+			Reason2 = output_file_not_up_to_date(TargetFile),
+			record_recompilation_reason(Reason2, RInfo0, RInfo)
+		}
+	    ), TargetFiles, Info4, Info5),
 
 	%
 	% Read in the used items, used for checking for
 	% ambiguities with new items.
 	%
-	read_term_check_for_error_or_eof(Info1, "used items",
+	read_term_check_for_error_or_eof(Info5, "used items",
 		UsedItemsTerm),
-	{ parse_used_items(Info1, UsedItemsTerm, UsedItems) },
-	{ Info2 = Info1 ^ used_items := UsedItems },
+	{ parse_used_items(Info5, UsedItemsTerm, UsedItems) },
+	{ Info6 = Info5 ^ used_items := UsedItems },
 
-	read_term_check_for_error_or_eof(Info2, "used classes",
+	read_term_check_for_error_or_eof(Info6, "used classes",
 		UsedClassesTerm),
 	{ 
 		UsedClassesTerm = term__functor(term__atom("used_classes"),
@@ -305,14 +314,14 @@
 				UsedClass = ClassName - ClassArity
 			), UsedClassTerms, UsedClasses)
 	->
-		Info3 = Info2 ^ used_typeclasses :=
+		Info7 = Info6 ^ used_typeclasses :=
 					set__list_to_set(UsedClasses)
 	;
 		Reason3 = syntax_error(get_term_context(UsedClassesTerm),
 				"error in used_typeclasses term"),
-		throw_syntax_error(Reason3, Info2)
+		throw_syntax_error(Reason3, Info6)
 	},
-	check_imported_modules(Info3, Info).
+	check_imported_modules(Info7, Info).
 
 
 %-----------------------------------------------------------------------------%
@@ -693,8 +702,8 @@
 				UsedItemsTerm, VersionNumbers,
 				OtherItems, Info1, Info)
 		;
-			throw(recompile_exception(
-				module_changed(FileName), Info1))
+			record_recompilation_reason(module_changed(FileName),
+				Info1, Info)
 		)
 	;
 		Error \= no_module_errors
@@ -768,10 +777,9 @@
 	{ set__difference(set__intersect(UsedClasses, ModuleInstances),
 		UsedInstances, AddedInstances) },
 	( { [AddedInstance | _] = set__to_sorted_list(AddedInstances) } ->
-		=(Info),
 		{ Reason1 = changed_or_added_instance(ModuleName,
 				AddedInstance) },
-		{ throw(recompile_exception(Reason1, Info)) }
+		record_recompilation_reason(Reason1)
 	;
 		[]
 	).
@@ -800,17 +808,15 @@
 			( { NewVersionNumber = UsedVersionNumber } ->
 				[]
 			;
-				=(Info),
 				{ Reason = changed_item(
 					make_item_id(ModuleName, ItemType,
 						NameArity)) },
-				{ throw(recompile_exception(Reason, Info)) }
+				record_recompilation_reason(Reason)
 			)
 		;
-			=(Info),
 			{ Reason = removed_item(make_item_id(ModuleName,
 						ItemType, NameArity)) },
-			{ throw(recompile_exception(Reason, Info)) }
+			record_recompilation_reason(Reason)
 		)
 	    ),
 	    extract_ids(UsedVersionNumbers, ItemType)).
@@ -832,13 +838,11 @@
 			;
 				{ Reason = changed_or_added_instance(
 					ModuleName, ClassId) },
-				=(Info),
-				{ throw(recompile_exception(Reason, Info)) }
+				record_recompilation_reason(Reason)
 			)
 		;
 			{ Reason = removed_instance(ModuleName, ClassId) },
-			=(Info),
-			{ throw(recompile_exception(Reason, Info)) }
+			record_recompilation_reason(Reason)
 		)
 	    ), UsedInstanceVersionNumbers).
 
@@ -1037,8 +1041,7 @@
 		{ Reason = item_ambiguity(item_id(ItemType, SymName - Arity), 
 				[item_id(ItemType, OldMatchingName - Arity)]
 			) },
-		=(Info),
-		{ throw(recompile_exception(Reason, Info)) }
+		record_recompilation_reason(Reason)
 	;
 		[]
 	).
@@ -1077,8 +1080,7 @@
 		{ Reason = item_ambiguity(item_id(ItemType, SymName - Arity), 
 				AmbiguousDecls
 		) },
-		=(Info),
-		{ throw(recompile_exception(Reason, Info)) }
+		record_recompilation_reason(Reason)
 	;
 		[]
 	).
@@ -1230,8 +1232,7 @@
 				ResolvedCtor,
 				set__to_sorted_list(OldResolvedCtors)
 			) },
-		=(Info),
-		{ throw(recompile_exception(Reason, Info)) }
+		record_recompilation_reason(Reason)
 	;
 		[]
 	).
@@ -1246,7 +1247,9 @@
 		read_modules :: read_modules,
 		used_items :: resolved_used_items,
 		used_typeclasses :: set(item_name),
-		modules_to_recompile :: modules_to_recompile
+		modules_to_recompile :: modules_to_recompile,
+		collect_all_reasons :: bool,
+		recompilation_reasons :: list(recompile_reason)
 	).
 
 :- type recompile_exception
@@ -1494,6 +1497,17 @@
 		Context
 	;
 		term__context_init
+	).
+
+:- pred record_recompilation_reason(recompile_reason::in,
+	recompilation_check_info::in, recompilation_check_info::out) is det.
+
+record_recompilation_reason(Reason, Info0, Info) :-
+	( Info0 ^ collect_all_reasons = yes ->
+		Info = Info0 ^ recompilation_reasons :=
+				[Reason | Info0 ^ recompilation_reasons]
+	;
+		throw(recompile_exception(Reason, Info0))
 	).
 
 :- pred throw_syntax_error(recompile_reason::in,
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.292
diff -u -u -r1.292 user_guide.texi
--- doc/user_guide.texi	12 Feb 2002 16:36:10 -0000	1.292
+++ doc/user_guide.texi	22 Feb 2002 15:31:06 -0000
@@ -3592,6 +3592,12 @@
 explaining why a module needs to be recompiled.
 
 @sp 1
+ at item --find-all-recompilation-reasons
+ at findex --find-all-recompilation-reasons
+Find all the reasons why a module needs to be recompiled,
+not just the first.  Implies @samp{--verbose-recompilation}.
+
+ at sp 1
 @item -S
 @itemx --statistics
 @findex -S
Index: tests/recompilation/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/recompilation/Mmakefile,v
retrieving revision 1.7
diff -u -u -r1.7 Mmakefile
--- tests/recompilation/Mmakefile	26 Oct 2001 02:24:05 -0000	1.7
+++ tests/recompilation/Mmakefile	22 Feb 2002 15:29:11 -0000
@@ -27,7 +27,7 @@
 # The `override' is needed because otherwise make ignores the assignment if
 # EXTRA_MCFLAGS is set on the command line, as it is for the nightly tests.
 override EXTRA_MCFLAGS += --no-intermodule-optimization --smart-recompilation \
-			--verbose-recompilation
+			--find-all-recompilation-reasons
 
 # This module tests recompilation of a module which depends on a module
 # for which no version numbers have been computed.
Index: tests/recompilation/remove_type_re.err_exp.2
===================================================================
RCS file: /home/mercury1/repository/tests/recompilation/remove_type_re.err_exp.2,v
retrieving revision 1.1
diff -u -u -r1.1 remove_type_re.err_exp.2
--- tests/recompilation/remove_type_re.err_exp.2	27 Jun 2001 05:05:15 -0000	1.1
+++ tests/recompilation/remove_type_re.err_exp.2	23 Feb 2002 06:01:19 -0000
@@ -1,5 +1,7 @@
 Recompiling module `remove_type_re':
   type `remove_type_re_2:foo/0' was removed.
+Recompiling module `remove_type_re':
+  body of type `remove_type_re_2:foo/0' was removed.
 remove_type_re.m:016: In definition of predicate `remove_type_re:output_foo'/3:
 remove_type_re.m:016:   error: undefined type `foo'/0.
 For more information, try recompiling with `-E'.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list