[m-rev.] for review: smart recompilation

Simon Taylor stayl at cs.mu.OZ.AU
Thu Jun 21 22:03:43 AEST 2001


On 05-Jun-2001, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> On 28-May-2001, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> > Index: doc/user_guide.texi
> > --- library/io.m	2001/05/02 14:44:26	1.224
> ...
> > +:- pred io__file_modification_time(string, io__res(time_t),
> > +		io__state, io__state).
> > +:- mode io__file_modification_time(in, out, di, uo) is det.
> > +	% io__file_modification_time(FileName, TimeResult)
> > +	% finds the last modification time of the given file.
> > +	% This predicate will only work on systems which provide
> > +	% the C library function stat(). On other systems the
> > +	% returned result will always be bound to error/1.
> 
> s/C/Posix C/

Done.
 
> The interface with time_t and the documentation there are both overly
> implementation-specific.
> This should return an abstract type, e.g. `file_timestamp'.
> 
> The documentation should not require changing if we happen to
> implement it on a non-Posix system (e.g. one that provides `_stat()'
> or `GetFileTimeStamp()' rather than stat()).

As explained in an earlier mail, I'll leave this as it is.

> > +:- pred io__input_stream_file_modification_time(io__input_stream,
> > +		io__res(time_t), io__state, io__state).
> > +:- mode io__input_stream_file_modification_time(in, out, di, uo) is det.
> 
> Is this really needed?

Removed.

> > +:- pred io__file_modification_time_2(string, int, string, time_t,
> > +		io__state, io__state).
> > +:- mode io__file_modification_time_2(in, out, out, out, di, uo) is det.
> > +
> > +:- pragma foreign_proc("C", io__file_modification_time_2(FileName::in,
> > +		Status::out, Msg::out, Time::out, IO0::di, IO::uo),
> > +		[will_not_call_mercury, thread_safe],
> > +"{
> > +#ifdef HAVE_STAT
> > +	struct stat s;
> > +	if (stat(FileName, &s) == 0) {
> > +		Time = s.st_mtime;
> 
> Here you are assuming that a C time_t will fit into an MR_Word.
> There should at least be an XXX comment.

Done.

> > Index: tests/recompilation/TESTS
> > ===================================================================
> It would be very helpful to have a comment at the top of this file
> explaining what the file is for; is this a shell script, a Makefile
> fragment, or something else?  Perhaps the file should be renamed to
> make this clear.

Done.

> > --- /dev/null	Mon Apr 16 11:57:05 2001
> > +++ add_constructor_r_2.err_exp.2	Tue May 22 17:36:07 2001
> > @@ -0,0 +1,2 @@
> > +Recompiling module `add_constructor_r_2':
> > +  add_constructor_r_2.m has changed.
> 
> I suggest changing the message to
> 
>      source file `add_constructor_r_2.m' has changed.

Done.
 
> You might also want to consider changing the ":\n  " to ",\n  because ".

I prefer the `:\n"' form.

> > Index: tests/recompilation/add_instance_2_r.exp.1
> > ===================================================================
> > @@ -0,0 +1 @@
> > +a
> > \ No newline at end of file
> 
> Text files without newlines at the end are not completely portable.
> You should change the program being tested so that it outputs a newline.

Done.

> > --- /dev/null	Mon Apr 16 11:57:05 2001
> > +++ add_type_re_2.err_exp.2	Mon May 28 15:15:20 2001
> > @@ -0,0 +1,2 @@
> > +Recompiling module `add_type_re_2':
> > +  add_type_re_2.used: file not found.
> 
> For that message I suggest
> 
>      file `add_type_re_2.used' not found.
> 
> or
> 
>      recompilation dependency file `add_type_re_2.used' not found.

Done.
 
> > Index: tests/recompilation/test_functions
> > ===================================================================
> > RCS file: test_functions
> > diff -N test_functions
> > --- /dev/null	Mon Apr 16 11:57:05 2001
> > +++ test_functions	Mon May 28 17:34:28 2001
> > @@ -0,0 +1,185 @@
> > +		cp -f $module.m.1 $module.m
> 
> I'm not sure how portable the `-f' option to `cp' is.

Changed to `rm -f $module.m; cp $module.m.1 $module.m'.
 
> > +mmake_depend () {
> > +	if mmake $main_module.depend
> > +	then
> > +		:
> > +	else 
> > +		exit 1
> > +	fi
> > +}
> 
> I'd advise writing that more concisely, as
> 
> 	mmake $main_module.depend || exit 1
>
> But you should also pass $mmake_opts (which is set by handle_options)
> to mmake.  (That also requires invoking it as `eval mmake ...' to get
> the quoting right.)

Done.
 
> > +	if [ -f $exp_file ]
> > +	then
> > +		if diff -c $exp_file $res_file >> $main_module.res
> 
> Rather than hard-coding `-c', it would be nicer to use `${DIFF_OPTS-"-c"}'.

Done.
 
> > +		then
> > +			:
> > +		else
> > +			exit 1
> > +		fi
> 
> You should print out an error message before exiting.

Done.

> > +		#
> > +		# If the compilation is supposed to fail then the mmake
> > +		# output should be suppressed to avoid making it harder
> > +		# to find genuine failures in the nightly test logs.
> > +		#
> > +		mmake $main_module > /dev/null 2>&1
> 
> It would be better to put the output in a log file rather than /dev/null.

Done.
 
> Also you should pass $mmake_opts to mmake, as is done in
> the other tests/*/runtests scripts.

Done.
 
> > +		"Error: mmake $main_module succeeded where it should fail"
> > +			exit 1
> > +			;;
> 
> Please make sure all error messages from test case failures start with "**",
> so that we can easily grep for them in the test logs.

Done.
 
Simon.

--- NEWS	2001/06/21 10:13:02	1.1
+++ NEWS	2001/06/21 10:17:27
@@ -30,10 +30,8 @@
 * The exception module has a new predicate `try_store', which is
   like `try_io', but which works with stores rather than io__states.
 
-* We've added predicates to io.m to find the last modification time
-  of files and input streams (io__file_modification_time,
-  io__input_stream_file_modification_time,
-  io__binary_input_stream_file_modification_time).
+* We've added a predicate to io.m to return the last modification time
+  of a file (io__file_modification_time).
 
 * We've added a predicate version of `set__fold'.
 
Index: timestamp.m
===================================================================
RCS file: timestamp.m
diff -N timestamp.m
--- /dev/null	Mon Apr 16 11:57:05 2001
+++ timestamp.m	Tue Jun  5 03:58:56 2001
@@ -0,0 +1,144 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2001 University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+% File: timestamp.m
+% Main author: stayl
+%
+% Timestamp representation for smart recompilation.
+%-----------------------------------------------------------------------------%
+:- module timestamp.
+
+:- interface.
+
+:- import_module time.
+
+	% A `timestamp' is similar to a `time_t' except that
+	% timestamps are system independent. A timestamp string
+	% (obtained using time__timestamp_to_string) written on
+	% one system can be read on any other system.
+	% Comparison of values of type `timestamp' (via compare/3)
+	% is equivalent to comparison of the times represented.
+:- type timestamp.
+
+	% time__time_t_to_timestamp(Time) = Timestamp:
+	%	Converts the calendar time value `Time' into a timestamp.
+	%	Equivalent to `gm_time_to_timestamp(gmtime(Time))'.
+:-func time_t_to_timestamp(time_t) = timestamp.
+
+	% time__timestamp_to_string(Timestamp) = String:
+	%	Converts `Timestamp' into a string with format
+	%	"yyyy-mm-dd hh:mm:ss", expressed as UTC. 
+:- func timestamp_to_string(timestamp) = string.
+
+	% time__string_to_timestamp(String) = Timestamp:
+	%	Converts a string formatted as "yyyy-mm-dd hh:mm:ss",
+	%	into a timestamp. Fails if the string does not have the
+	%	correct format.
+:- func string_to_timestamp(string) = timestamp is semidet.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int, std_util, string.
+
+	% A timestamp is a string formatted as "yyyy-mm-dd hh:mm:ss"
+	% representing a time expressed as UTC (Universal Coordinated Time).
+:- type timestamp == string.
+
+:- pragma c_header_code("#include <time.h>").
+
+time_t_to_timestamp(Time) = gmtime_to_timestamp(time__gmtime(Time)).
+
+:- func gmtime_to_timestamp(tm) = timestamp.
+
+gmtime_to_timestamp(tm(Year, Month, MD, Hrs, Min, Sec, YD, WD, DST)) =
+	gmtime_to_timestamp(Year, Month, MD, Hrs, Min, Sec,
+		YD, WD, maybe_dst_to_int(DST)).
+
+:- func gmtime_to_timestamp(int, int, int, int,
+		int, int, int, int, int) = timestamp.
+
+:- pragma foreign_proc("C",
+	gmtime_to_timestamp(Yr::in, Mnt::in, MD::in, Hrs::in, Min::in, Sec::in,
+		YD::in, WD::in, N::in) = (Result::out),
+	[will_not_call_mercury],
+"{
+	int size;
+	struct tm t;
+
+	t.tm_sec = Sec;
+	t.tm_min = Min;
+	t.tm_hour = Hrs;
+	t.tm_mon = Mnt;
+	t.tm_year = Yr;
+	t.tm_wday = WD;
+	t.tm_mday = MD;
+	t.tm_yday = YD;
+	t.tm_isdst = N;
+
+	size = sizeof ""yyyy-mm-dd hh:mm:ss"";
+	MR_allocate_aligned_string_msg(Result, size - 1, MR_PROC_LABEL);
+
+	strftime(Result, size, ""%Y-%m-%d %H:%M:%S"", &t);
+}").
+
+:- pragma foreign_proc("MC++",
+	gmtime_to_timestamp(_Yr::in, _Mnt::in, _MD::in, _Hrs::in, _Min::in,
+		_Sec::in, _YD::in, _WD::in, _N::in) = (_Result::out),
+	[will_not_call_mercury],
+"{
+	mercury::runtime::Errors::SORRY(""foreign code for this function"");
+}").
+
+:- func maybe_dst_to_int(maybe(dst)) = int.
+
+maybe_dst_to_int(M) = N :-
+	( M = yes(DST), DST = daylight_time,
+		N = 1
+	; M = yes(DST), DST = standard_time,
+		N = 0
+	; M = no,
+		N = -1
+	).
+
+timestamp_to_string(Timestamp) = Timestamp.
+
+string_to_timestamp(Timestamp) = Timestamp :-
+	string__length(Timestamp) `with_type` int =
+		string__length("yyyy-mm-dd hh:mm:ss"),
+
+	string__to_int(string__unsafe_substring(Timestamp, 0, 4), _),
+
+	string__unsafe_index(Timestamp, 4, '-'),
+
+	string__to_int(string__unsafe_substring(Timestamp, 5, 2), Month),
+	Month >= 1,
+	Month =< 12,
+
+	string__unsafe_index(Timestamp, 7, '-'),
+
+	string__to_int(string__unsafe_substring(Timestamp, 8, 2), Day),
+	Day >= 1,
+	Day =< 31,
+
+	string__unsafe_index(Timestamp, 10, ' '),
+
+	string__to_int(string__unsafe_substring(Timestamp, 11, 2), Hour),
+	Hour >= 0,
+	Hour =< 23,
+
+	string__unsafe_index(Timestamp, 13, ':'),
+
+	string__to_int(string__unsafe_substring(Timestamp, 14, 2), Minute),
+	Minute >= 0,
+	Minute =< 59,
+
+	string__unsafe_index(Timestamp, 16, ':'),
+
+	string__to_int(string__unsafe_substring(Timestamp, 17, 2), Second),
+	Second >= 0,
+	Second =< 61.	% Seconds 60 and 61 are for leap seconds.
+
--- equiv_type.m	2001/05/29 04:37:40	1.2
+++ equiv_type.m	2001/06/04 17:58:56
@@ -27,7 +27,8 @@
 	%
 	% For items not defined in the current module, record the
 	% equivalence types expanded while processing each item
-	% in the recompilation_info.
+	% in the recompilation_info. This is needed for smart
+	% recompilation.
 :- pred equiv_type__expand_eqv_types(module_name, list(item_and_context),
 		list(item_and_context), bool, eqv_map,
 		maybe(recompilation_info), maybe(recompilation_info),
--- error_util.m	2001/05/29 04:37:40	1.2
+++ error_util.m	2001/06/04 17:58:56
@@ -58,7 +58,8 @@
 		list(format_component)::out) is det.
 
 	% Convert a list of lists of format_components into a list of
-	% format_components, suitable for displaying as an error message.
+	% format_components separated by commas, with the last two
+	% elements separated by `and'.
 :- func error_util__component_lists_to_pieces(list(list(format_component))) =
 		list(format_component).
 
@@ -99,6 +100,8 @@
 :- func error_util__describe_sym_name_and_arity(sym_name_and_arity) =
 			string.
 
+	% Append a punctuation character to a message, avoiding unwanted
+	% line splitting between the message and the punctuation.
 :- func error_util__append_punctuation(list(format_component), char) =
 		list(format_component).
 
@@ -474,10 +477,10 @@
 
 error_util__append_punctuation([], _) = _ :-
 	error(
-	"error_util__append_full_stop: appending punctuation after nothing").
+	"error_util__append_punctuation: appending punctuation after nothing").
 error_util__append_punctuation([Piece0], Punc) = [Piece] :-
-	% Avoid unwanted line splitting between the punctuation and the
-	% full-stop.	
+	% Avoid unwanted line splitting between the message
+	% and the punctuation.
 	(
 		Piece0 = words(String),
 		Piece = words(string__append(String, char_to_string(Punc)))
--- handle_options.m	2001/05/29 04:37:40	1.2
+++ handle_options.m	2001/06/04 17:58:56
@@ -368,7 +368,6 @@
 	option_implies(make_private_interface, smart_recompilation, bool(no)),
 	option_implies(make_interface, smart_recompilation, bool(no)),
 	option_implies(make_short_interface, smart_recompilation, bool(no)),
-	option_implies(make_short_interface, smart_recompilation, bool(no)),
 	option_implies(output_grade_string, smart_recompilation, bool(no)),
 	option_implies(make_optimization_interface,
 		smart_recompilation, bool(no)),
@@ -405,7 +404,7 @@
 	% it becomes difficult to work out what all the target
 	% files are and check whether they are up-to-date.
 	% By default, mmake always enables `--target-code-only' and
-	% processes the object file itself, so this isn't a problem.
+	% processes the target code file itself, so this isn't a problem.
 	maybe_disable_smart_recompilation(Smart, target_code_only, no,
 		"`--no-target-code-only'"),
 
--- make_hlds.m	2001/05/29 04:37:40	1.2
+++ make_hlds.m	2001/06/05 17:21:29
@@ -664,12 +664,14 @@
 add_item_clause(module_defn(_, Defn), Status0, Status, _,
 		Module0, Module, Info0, Info) --> 
 	{ Defn = version_numbers(ModuleName, ModuleVersionNumbers) ->
+		%
+		% Record the version numbers for each imported module
+		% if smart recompilation is enabled.
+		%
 		apply_to_recompilation_info(
 		    (pred(RecompInfo0::in, RecompInfo::out) is det :-
-			map__set(RecompInfo0 ^ version_numbers, ModuleName,
-				ModuleVersionNumbers, VersionNumbers),
-			RecompInfo = RecompInfo0 ^ version_numbers
-					:= VersionNumbers
+			RecompInfo = RecompInfo0 ^ version_numbers ^
+				map__elem(ModuleName) := ModuleVersionNumbers
 		    ),
 		    transform_info(Module0, Info0),
 		    transform_info(Module, Info)),
@@ -962,8 +964,13 @@
 		goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo1),
 		goal_info_set_context(GoalInfo1, Context, GoalInfo),
 
+		%
 		% We don't record the called predicate as used --
 		% it is only used if there is some other call.
+		% This call is only used to make higher_order.m generate
+		% the interface for the type specialized procedure, and
+		% will be removed by higher_order.m after that is done.
+		%
 		do_construct_pred_or_func_call(PredId, PredOrFunc, SymName,
 			Args, GoalInfo, Goal),
 		Clause = clause(ProcIds, Goal, Context),
--- mercury_compile.m	2001/05/29 04:37:40	1.2
+++ mercury_compile.m	2001/06/21 08:28:29
@@ -73,11 +73,12 @@
 :- import_module dependency_graph, prog_util, rl_dump, rl_file.
 :- import_module options, globals, trace_params, passes_aux.
 :- import_module recompilation, recompilation_usage, recompilation_check.
+:- import_module timestamp.
 
 	% library modules
 :- import_module int, list, map, set, std_util, dir, require, string, bool.
 :- import_module library, getopt, set_bbbtree, term, varset, assoc_list.
-:- import_module time, gc.
+:- import_module gc.
 
 %-----------------------------------------------------------------------------%
 
@@ -441,7 +442,7 @@
 	.
 
 :- pred read_module(file_or_module, bool, module_name, file_name,
-		maybe(time_t), item_list, module_error,
+		maybe(timestamp), item_list, module_error,
 		read_modules, read_modules, io__state, io__state).
 :- mode read_module(in, in, out, out, out, out, out, in, out, di, uo) is det.
 
@@ -453,6 +454,8 @@
 	maybe_write_string(Verbose, ModuleNameString),
 	maybe_write_string(Verbose, "' and imported interfaces...\n"),
 	(
+		% Avoid rereading the module if it was already read
+		% by recompilation_version.m.
 		{ find_read_module(ReadModules0, ModuleName, ".m",
 			ReturnTimestamp, Items0, MaybeTimestamp0,
 			Error0, FileName0) }
@@ -479,6 +482,8 @@
 
 	{ file_name_to_module_name(FileName, DefaultModuleName) },
 	(
+		% Avoid rereading the module if it was already read
+		% by recompilation_version.m.
 		{ find_read_module(ReadModules0, DefaultModuleName, ".m",
 			ReturnTimestamp, Items0, MaybeTimestamp0, Error0, _) }
 	->
@@ -613,8 +618,22 @@
 			{ find_smart_recompilation_target_files(
 				Globals, FindTargetFiles) },
 			recompilation_check__should_recompile(ModuleName,
-				FindTargetFiles, ModulesToRecompile,
-				ReadModules)
+				FindTargetFiles, ModulesToRecompile0,
+				ReadModules),
+			{
+				ModulesToRecompile0 = some([_ | _]),
+				globals__get_target(Globals, asm)
+			->
+				% 
+				% With `--target asm', if one module
+				% needs to be recompiled, all need to be
+				% recompiled because they are all compiled
+				% into a single object file.
+				%
+				ModulesToRecompile = (all)
+			;
+				ModulesToRecompile = ModulesToRecompile0
+			}
 		;
 			{ map__init(ReadModules) },
 			{ ModulesToRecompile = (all) }
@@ -655,9 +674,9 @@
 		;
 				SubModuleList = SubModuleList0	
 		},
-		{ assoc_list__keys(SubModuleList, InlineSubModules0) },
-		{ list__delete_all(InlineSubModules0,
-			ModuleName, InlineSubModules) },
+		{ assoc_list__keys(SubModuleList, NestedSubModules0) },
+		{ list__delete_all(NestedSubModules0,
+			ModuleName, NestedSubModules) },
 		(
 			{ any_mercury_builtin_module(ModuleName) }
 		->
@@ -675,7 +694,7 @@
 			globals__io_set_trace_level_none,
 
 			compile_all_submodules(FileName,
-				ModuleName - InlineSubModules,
+				ModuleName - NestedSubModules,
 				MaybeTimestamp, ReadModules, SubModuleList,
 				ModulesToLink),
 
@@ -683,7 +702,7 @@
 			globals__io_set_trace_level(TraceLevel)
 		;
 			compile_all_submodules(FileName,
-				ModuleName - InlineSubModules,
+				ModuleName - NestedSubModules,
 				MaybeTimestamp, ReadModules, SubModuleList,
 				ModulesToLink)
 		)
@@ -701,33 +720,33 @@
 	% i.e. compile nested modules to a single C file.
 
 :- pred compile_all_submodules(string, pair(module_name, list(module_name)),
-	maybe(time_t), read_modules, list(pair(module_name, item_list)),
+	maybe(timestamp), read_modules, list(pair(module_name, item_list)),
 	list(string), io__state, io__state).
 :- mode compile_all_submodules(in, in, in, in, in, out, di, uo) is det.
 
-compile_all_submodules(FileName, InlineSubModules, MaybeTimestamp,
+compile_all_submodules(FileName, NestedSubModules, MaybeTimestamp,
 		ReadModules, SubModuleList, ModulesToLink) -->
 	list__foldl(
-		compile(FileName, InlineSubModules,
+		compile(FileName, NestedSubModules,
 			MaybeTimestamp, ReadModules),
 		SubModuleList),
 	list__map_foldl(module_to_link, SubModuleList, ModulesToLink).
 
-:- pred make_interface(file_name, maybe(time_t), pair(module_name, item_list),
-			io__state, io__state).
+:- pred make_interface(file_name, maybe(timestamp),
+		pair(module_name, item_list), io__state, io__state).
 :- mode make_interface(in, in, in, di, uo) is det.
 
 make_interface(SourceFileName, MaybeTimestamp, ModuleName - Items) -->
 	make_interface(SourceFileName, ModuleName, MaybeTimestamp, Items).
 
-:- pred make_short_interface(file_name, maybe(time_t),
+:- pred make_short_interface(file_name, maybe(timestamp),
 		pair(module_name, item_list), io__state, io__state).
 :- mode make_short_interface(in, in, in, di, uo) is det.
 
 make_short_interface(SourceFileName, _, ModuleName - Items) -->
 	make_short_interface(SourceFileName, ModuleName, Items).
 
-:- pred make_private_interface(file_name, maybe(time_t),
+:- pred make_private_interface(file_name, maybe(timestamp),
 		pair(module_name, item_list), io__state, io__state).
 :- mode make_private_interface(in, in, in, di, uo) is det.
 
@@ -810,22 +829,22 @@
 	% so that new stages can be slotted in without too much trouble.
 
 :- pred compile(file_name, pair(module_name, list(module_name)),
-	maybe(time_t), read_modules, pair(module_name, item_list),
+	maybe(timestamp), read_modules, pair(module_name, item_list),
 	io__state, io__state).
 :- mode compile(in, in, in, in, in, di, uo) is det.
 
-compile(SourceFileName, RootModuleName - InlineSubModules0,
+compile(SourceFileName, RootModuleName - NestedSubModules0,
 		MaybeTimestamp, ReadModules, ModuleName - Items) -->
 	check_for_no_exports(Items, ModuleName),
 	grab_imported_modules(SourceFileName, ModuleName, ReadModules,
 		MaybeTimestamp, Items, Module, Error2),
 	( { Error2 \= fatal } ->
 		{ ModuleName = RootModuleName ->
-			InlineSubModules = InlineSubModules0
+			NestedSubModules = NestedSubModules0
 		;
-			InlineSubModules = []
+			NestedSubModules = []
 		},
-		mercury_compile(Module, InlineSubModules)
+		mercury_compile(Module, NestedSubModules)
 	;
 		[]
 	).
@@ -834,7 +853,7 @@
 		io__state, io__state).
 :- mode mercury_compile(in, in, di, uo) is det.
 
-mercury_compile(Module, InlineSubModules) -->
+mercury_compile(Module, NestedSubModules) -->
 	{ module_imports_get_module_name(Module, ModuleName) },
 	% If we are only typechecking or error checking, then we should not
 	% modify any files, this includes writing to .d files.
@@ -897,7 +916,7 @@
 		%
 		module_name_to_file_name(ModuleName, ".used", no,
 			UsageFileName),
-		invoke_system_command("rm -f " ++ UsageFileName, _),
+		io__remove_file(UsageFileName, _),
 
 		% magic sets can report errors.
 		{ module_info_num_errors(HLDS50, NumErrors) },
@@ -988,7 +1007,7 @@
 				MaybeRLFile, ModuleName, _CompileErrors)
 		    ),
 		    recompilation_usage__write_usage_file(HLDS,
-		    	InlineSubModules, MaybeTimestamps)
+		    	NestedSubModules, MaybeTimestamps)
 		;
 		    	% If the number of errors is > 0, make sure that
 			% the compiler exits with a non-zero exit
--- modules.m	2001/05/29 04:37:40	1.2
+++ modules.m	2001/06/08 07:33:22
@@ -39,8 +39,8 @@
 
 :- interface.
 
-:- import_module prog_data, prog_io, globals.
-:- import_module std_util, bool, list, map, set, io, time.
+:- import_module prog_data, prog_io, globals, timestamp.
+:- import_module std_util, bool, list, map, set, io.
 
 %-----------------------------------------------------------------------------%
 
@@ -144,19 +144,32 @@
 	%	use `read_mod_from_file'.
 	%
 :- pred read_mod(module_name, string, string, bool, bool,
-		item_list, module_error, file_name, maybe(time_t),
+		item_list, module_error, file_name, maybe(timestamp),
 		io__state, io__state).
 :- mode read_mod(in, in, in, in, in, out, out, out, out, di, uo) is det.
 
-:- pred read_mod_if_changed(module_name, string, string, bool, time_t,
-		item_list, module_error, file_name, maybe(time_t),
+	% read_mod_if_changed(ModuleName, Extension, Descr, Search,
+	%	OldTimestamp, Items, Error, SourceFileName,
+	%	MaybeTimestamp):
+	%
+	%	If the timestamp of the file specified by the given
+	%	module name and file extension is newer than OldTimestamp,
+	%	read the file, returning the new timestamp.
+	%
+	%	If the file was read, MaybeTimestamp will contain the
+	%	new timestamp.
+	%	If the timestamp was unchanged, MaybeTimestamp will
+	%	be `yes(OldTimestamp)'.
+	%	If the file could not be read, MaybeTimestamp will be `no'.
+:- pred read_mod_if_changed(module_name, string, string, bool, timestamp,
+		item_list, module_error, file_name, maybe(timestamp),
 		io__state, io__state).
 :- mode read_mod_if_changed(in, in, in, in, in,
 		out, out, out, out, di, uo) is det.
 
 	% Similar to read_mod, but doesn't return error messages.
 :- pred read_mod_ignore_errors(module_name, string, string, bool, bool,
-		item_list, module_error, file_name, maybe(time_t),
+		item_list, module_error, file_name, maybe(timestamp),
 		io__state, io__state).
 :- mode read_mod_ignore_errors(in, in, in, in, in, out, out, out, out,
 		di, uo) is det.
@@ -178,8 +191,8 @@
 	%	use `read_mod'.
 	%
 :- pred read_mod_from_file(file_name, string, string, bool, bool,
-		item_list, module_error, module_name, maybe(time_t),
-		io__state, io__state).
+		item_list, module_error, module_name,
+		maybe(timestamp), io__state, io__state).
 :- mode read_mod_from_file(in, in, in, in, in, out, out, out, out,
 		di, uo) is det.
 
@@ -195,8 +208,8 @@
 	%	the module, including those in the `implementation'
 	%	section; it is used when compiling sub-modules.)
 	%
-:- pred make_private_interface(file_name, module_name, maybe(time_t),
-		item_list, io__state, io__state).
+:- pred make_private_interface(file_name, module_name,
+		maybe(timestamp), item_list, io__state, io__state).
 :- mode make_private_interface(in, in, in, in, di, uo) is det.
 
 	% make_interface(SourceFileName, ModuleName, MaybeTimestamp, Items):
@@ -206,7 +219,7 @@
 	%	output the long (`.int') and short (`.int2') interface files
 	%	for the module.
 	%
-:- pred make_interface(file_name, module_name, maybe(time_t),
+:- pred make_interface(file_name, module_name, maybe(timestamp),
 		item_list, io__state, io__state).
 :- mode make_interface(in, in, in, in, di, uo) is det.
 
@@ -288,7 +301,7 @@
 :- type module_timestamp
 	--->	module_timestamp(
 			suffix :: string,
-			timestamp :: time_t,
+			timestamp :: timestamp,
 			need_qualifier :: need_qualifier
 		).
 
@@ -310,7 +323,7 @@
 	%
 	% Check whether a file was read during recompilation checking.
 :- pred find_read_module(read_modules, module_name, string, bool, item_list,
-		maybe(time_t), module_error, file_name).
+		maybe(timestamp), module_error, file_name).
 :- mode find_read_module(in, in, in, in, out, out, out, out) is semidet.
 
 % Some access predicates for the module_imports structure
@@ -398,7 +411,7 @@
 	%	recompilation checking.
 	%
 :- pred grab_imported_modules(file_name, module_name, read_modules,
-		maybe(time_t), item_list, module_imports,
+		maybe(timestamp), item_list, module_imports,
 		module_error, io__state, io__state).
 :- mode grab_imported_modules(in, in, in, in, in, out, out, di, uo) is det.
 
@@ -1195,11 +1208,11 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred write_interface_file(file_name, module_name, string, maybe(time_t),
-		item_list, io__state, io__state).
+:- pred write_interface_file(file_name, module_name, string,
+		maybe(timestamp), item_list, io__state, io__state).
 :- mode write_interface_file(in, in, in, in, in, di, uo) is det.
 
-write_interface_file(SourceFileName, ModuleName, Suffix,
+write_interface_file(_SourceFileName, ModuleName, Suffix,
 		MaybeTimestamp, InterfaceItems0) -->
 
 		% Create (e.g.) `foo.int.tmp'.
@@ -1243,8 +1256,8 @@
 				[VersionNumberItem | InterfaceItems0] }
 		;
 			{ MaybeTimestamp = no },
-			{ InterfaceItems1 = InterfaceItems0 },
-			report_modification_time_warning(SourceFileName)
+			{ error(
+"write_interface_file with `--smart-recompilation', timestamp not read") }
 		)
 	;
 		{ InterfaceItems1 = InterfaceItems0 }
@@ -3760,7 +3773,7 @@
 %-----------------------------------------------------------------------------%
 
 :- pred read_mod(read_modules, module_name, string, string, bool, bool,
-		item_list, module_error, file_name, maybe(time_t),
+		item_list, module_error, file_name, maybe(timestamp),
 		io__state, io__state).
 :- mode read_mod(in, in, in, in, in, in, out, out, out, out, di, uo) is det.
 
@@ -3797,8 +3810,8 @@
 		no, ReturnTimestamp, Items, Error, FileName, MaybeTimestamp).
 
 :- pred read_mod_2(bool, module_name, module_name, string, string,
-		bool, maybe(time_t), bool, item_list, module_error,
-		file_name, maybe(time_t), io__state, io__state).
+		bool, maybe(timestamp), bool, item_list, module_error,
+		file_name, maybe(timestamp), io__state, io__state).
 :- mode read_mod_2(in, in, in, in, in, in, in, in, out, out, out, out,
 		di, uo) is det.
 
@@ -3824,6 +3837,7 @@
 	),
 	check_module_has_expected_name(FileName0,
 		ModuleName, ActualModuleName),
+
 	%
 	% if that didn't work, and we're reading in the source (.m)
 	% file for a nested module, try again after dropping one 
@@ -3842,6 +3856,7 @@
 			ReturnTimestamp, Items, Error, FileName,
 			MaybeTimestamp)
 	;
+		check_timestamp(FileName0, MaybeTimestamp0, MaybeTimestamp),
 		( { IgnoreErrors = yes } ->
 			(
 				{ Error0 = fatal },
@@ -3862,22 +3877,12 @@
 				io__set_exit_status(1)
 			;
 				maybe_write_string(VeryVerbose,
-					"successful parse.\n"),
-				(
-					{ ReturnTimestamp = yes },
-					{ MaybeTimestamp = no }
-				->
-					report_modification_time_warning(
-						FileName)
-				;
-					[]
-				)
+					"successful parse.\n")
 			),
 			prog_out__write_messages(Messages)
 		),
 		{ Error = Error0 },
 		{ Items = Items0 },
-		{ MaybeTimestamp = MaybeTimestamp0 },
 		{ FileName = FileName0 }
 	).
 
@@ -3895,7 +3900,8 @@
 	{ file_name_to_module_name(BaseFileName, DefaultModuleName) },
 	prog_io__read_module(FullFileName, DefaultModuleName, Search,
 		ReturnTimestamp, Error, ModuleName, Messages, Items,
-		MaybeTimestamp),
+		MaybeTimestamp0),
+	check_timestamp(FullFileName, MaybeTimestamp0, MaybeTimestamp),
 	( { Error = fatal } ->
 		maybe_write_string(VeryVerbose, "fatal error(s).\n"),
 		io__set_exit_status(1)
@@ -3907,6 +3913,24 @@
 	),
 	prog_out__write_messages(Messages).
 
+:- pred check_timestamp(file_name, maybe(io__res(timestamp)), maybe(timestamp), 
+		io__state, io__state).
+:- mode check_timestamp(in, in, out, di, uo) is det.
+
+check_timestamp(FileName, MaybeTimestamp0, MaybeTimestamp) -->
+	(
+		{ MaybeTimestamp0 = yes(ok(Timestamp)) },
+		{ MaybeTimestamp = yes(Timestamp) }
+	;
+		{ MaybeTimestamp0 = yes(error(IOError)) },
+		{ MaybeTimestamp = no },
+		report_modification_time_warning(
+			FileName, IOError)
+	;
+		{ MaybeTimestamp0 = no },
+		{ MaybeTimestamp = no }
+	).
+
 /*
 :- pred combine_module_errors(module_error, module_error, module_error).
 :- mode combine_module_errors(in, in, out) is det.
@@ -3964,10 +3988,10 @@
 		read_mod(ReadModules, Ancestor, ".int0",
 			"Reading private interface for module", yes,
 			ReturnTimestamp, PrivateIntItems, PrivateIntError,
-			AncestorFileName, MaybeTimestamp),
+			_AncestorFileName, MaybeTimestamp),
 
 		maybe_record_timestamp(Ancestor, ".int0", may_be_unqualified,
-			AncestorFileName, MaybeTimestamp, Module0, Module1),
+			MaybeTimestamp, Module0, Module1),
 
 		{ strip_off_interface_decl(PrivateIntItems, Items) },
 		{ maybe_add_int_error(PrivateIntError, ModError0, ModError) },
@@ -4022,7 +4046,7 @@
 		},
 		read_mod(ReadModules, Import, Ext,
 			"Reading interface for module", yes, ReturnTimestamp,
-			LongIntItems, LongIntError, LongIntFileName,
+			LongIntItems, LongIntError, _LongIntFileName,
 			MaybeTimestamp),
 
 		{ strip_off_interface_decl(LongIntItems, Items) },
@@ -4037,8 +4061,7 @@
 			{ Module1 = Module0 }
 		;
 			maybe_record_timestamp(Import, Ext, NeedQualifier,
-				LongIntFileName, MaybeTimestamp,
-				Module0, Module1),
+				MaybeTimestamp, Module0, Module1),
 			{ ModImplementationImports =
 				[Import | ModImplementationImports0] },
 			check_module_accessibility(ModuleName, Import,
@@ -4216,9 +4239,9 @@
 		read_mod(ReadModules, Import, Ext,
 			"Reading short interface for module", yes,
 			ReturnTimestamp, ShortIntItems, ShortIntError,
-			ImportFileName, MaybeTimestamp),
+			_ImportFileName, MaybeTimestamp),
 		maybe_record_timestamp(Import, Ext, must_be_qualified,
-			ImportFileName, MaybeTimestamp, Module0, Module1),
+			MaybeTimestamp, Module0, Module1),
 
 		{ strip_off_interface_decl(ShortIntItems, Items) },
 		{ maybe_add_int_error(ShortIntError, ModError0, ModError) },
@@ -4801,16 +4824,18 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred maybe_record_timestamp(module_name, string, need_qualifier, file_name,
-	maybe(time_t), module_imports, module_imports, io__state, io__state).
-:- mode maybe_record_timestamp(in, in, in, in, in, in, out, di, uo) is det.
+:- pred maybe_record_timestamp(module_name, string, need_qualifier,
+	maybe(timestamp), module_imports, module_imports,
+	io__state, io__state).
+:- mode maybe_record_timestamp(in, in, in, in, in, out, di, uo) is det.
 
-maybe_record_timestamp(ModuleName, Suffix, NeedQualifier, FileName,
+maybe_record_timestamp(ModuleName, Suffix, NeedQualifier,
 		MaybeTimestamp, Module0, Module) -->
 	(
 		{ Module0 ^ maybe_timestamps = yes(Timestamps0) }
 	->
-		( { MaybeTimestamp = yes(Timestamp) } ->
+		(
+			{ MaybeTimestamp = yes(Timestamp) },
 			{ TimestampInfo = module_timestamp(Suffix,
 						Timestamp, NeedQualifier) },
 			{ map__set(Timestamps0, ModuleName,
@@ -4818,24 +4843,31 @@
 			{ Module = Module0 ^ maybe_timestamps :=
 					yes(Timestamps) }
 		;
-			{ Module = Module0 },
-			report_modification_time_warning(FileName)
+			{ MaybeTimestamp = no },
+			{ Module = Module0 }
 		)
 	;
 		{ Module = Module0 }
 	).
 
-:- pred report_modification_time_warning(file_name, io__state, io__state).
-:- mode report_modification_time_warning(in, di, uo) is det.
+:- pred report_modification_time_warning(file_name, io__error,
+		io__state, io__state).
+:- mode report_modification_time_warning(in, in, di, uo) is det.
 
-report_modification_time_warning(SourceFileName) -->
+report_modification_time_warning(SourceFileName, Error) -->
 	globals__io_set_option(smart_recompilation, bool(no)),
+	globals__io_set_option(generate_item_version_numbers, bool(no)),
 	globals__io_lookup_bool_option(warn_smart_recompilation, Warn),
 	( { Warn = yes } ->
 		io__write_string(
 			"Warning: cannot find modification time for "),
 		io__write_string(SourceFileName),
-		io__write_string(".\nSmart recompilation will not work.\n"),
+		io__write_string(":\n"),
+		{ io__error_message(Error, Msg) },
+		io__write_string("  "),
+		io__write_string(Msg),
+		io__write_string(".\n"),
+		io__write_string("  Smart recompilation will not work.\n"),
 		globals__io_lookup_bool_option(halt_at_warn, HaltAtWarn),
 		( { HaltAtWarn = yes } ->
 			io__set_exit_status(1)	
--- prog_data.m	2001/05/29 04:37:40	1.2
+++ prog_data.m	2001/06/05 12:23:23
@@ -51,7 +51,7 @@
 
 	; 	type_defn(tvarset, sym_name, list(type_param),
 			type_defn, condition)
-		%	VarNames, Name, Args, TypeDefn, Condition
+		%	VarNames, TypeName, Args, TypeDefn, Condition
 
 	; 	inst_defn(inst_varset, sym_name, list(inst_var),
 			inst_defn, condition)
@@ -690,6 +690,16 @@
 	% type_id and a list of arguments.
 	% type_util:construct_type to construct a type from a type_id 
 	% and a list of arguments.
+	%
+	% The `term__context's of the type terms must be empty (as
+	% returned by term__context_init). prog_io_util__convert_type
+	% ensures this is the case. There are at least two reasons that this
+	% is required:
+	% - Various parts of the code to handle typeclasses creates maps
+	%   indexed by `class_constraint's, which contain types.
+	% - Smart recompilation requires that the items which occur in
+	%   interface files can be unified using the builtin unification
+	%   operation.
 :- type (type)		==	term(tvar_type).
 :- type type_term	==	term(tvar_type).
 
--- prog_io.m	2001/05/29 04:37:40	1.2
+++ prog_io.m	2001/06/08 07:36:17
@@ -55,8 +55,8 @@
 
 :- interface.
 
-:- import_module prog_data, prog_io_util.
-:- import_module bool, varset, term, list, io, time, std_util. 
+:- import_module prog_data, prog_io_util, timestamp.
+:- import_module bool, varset, term, list, io, std_util. 
 
 %-----------------------------------------------------------------------------%
 
@@ -89,13 +89,13 @@
 
 :- pred prog_io__read_module(file_name, module_name, bool, bool,
 		module_error, module_name, message_list, item_list,
-		maybe(time_t), io__state, io__state).
+		maybe(io__res(timestamp)), io__state, io__state).
 :- mode prog_io__read_module(in, in, in, in, out, out, out, out,
 		out, di, uo) is det.
 
-:- pred prog_io__read_module_if_changed(file_name, module_name, bool, time_t,
-		module_error, module_name, message_list,
-		item_list, maybe(time_t), io__state, io__state).
+:- pred prog_io__read_module_if_changed(file_name, module_name, bool,
+		timestamp, module_error, module_name, message_list,
+		item_list, maybe(io__res(timestamp)), io__state, io__state).
 :- mode prog_io__read_module_if_changed(in, in, in, in,
 		out, out, out, out, out, di, uo) is det.
 
@@ -199,7 +199,7 @@
 :- import_module recompilation, recompilation_version.
 
 :- import_module int, string, std_util, parser, term_io, dir, require.
-:- import_module assoc_list, map.
+:- import_module assoc_list, map, time.
 
 %-----------------------------------------------------------------------------%
 
@@ -250,10 +250,10 @@
 % late-input modes.)
 
 :- pred prog_io__read_module_2(file_name, module_name, bool, option,
-		maybe(time_t), bool, module_error, module_name, message_list,
-		item_list, maybe(time_t), io__state, io__state).
+	maybe(timestamp), bool, module_error, module_name, message_list,
+	item_list, maybe(io__res(timestamp)), io__state, io__state).
 :- mode prog_io__read_module_2(in, in, in, in, in, in, out, out, out, out,
-		out, di, uo) is det.
+	out, di, uo) is det.
 
 prog_io__read_module_2(FileName, DefaultModuleName, Search, SearchOpt,
 		MaybeOldTimestamp, ReturnTimestamp, Error,
@@ -271,22 +271,23 @@
 	search_for_file(Dirs, FileName, R),
 	( { R = yes } ->
 		( { ReturnTimestamp = yes } ->
-			io__input_stream(InputStream),
-			io__input_stream_file_modification_time(InputStream,
+			io__input_stream_name(InputStreamName),
+			io__file_modification_time(InputStreamName,
 				TimestampResult),
 			(
 				{ TimestampResult = ok(Timestamp) },
-				{ MaybeModuleTimestamp = yes(Timestamp) } 
+				{ MaybeModuleTimestamp = yes(
+					ok(time_t_to_timestamp(Timestamp))) }
 			;
-				{ TimestampResult = error(_) },
-				{ MaybeModuleTimestamp = no }
+				{ TimestampResult = error(IOError) },
+				{ MaybeModuleTimestamp = yes(error(IOError)) }
 			)
 		;
 			{ MaybeModuleTimestamp = no }
 		),
 		(
 			{ MaybeOldTimestamp = yes(OldTimestamp) },
-			{ MaybeModuleTimestamp = yes(OldTimestamp) }
+			{ MaybeModuleTimestamp = yes(ok(OldTimestamp)) }
 		->
 			%
 			% XXX Currently smart recompilation won't work
--- recompilation.m	2001/05/29 04:37:40	1.2
+++ recompilation.m	2001/06/04 17:58:56
@@ -23,18 +23,20 @@
 
 :- interface.
 
-:- import_module prog_data.
-:- import_module io, map, set, std_util, time.
+:- import_module prog_data, timestamp.
+:- import_module io, map, set, std_util, term.
 
 	% Identify a particular version of a program item.
 	% This could be done using a timestamp or a hash value. 
-:- type version_number == time_t.
-
-:- func int_to_version_number(int) = version_number.
+:- type version_number == timestamp.
 
 :- pred write_version_number(version_number::in,
 		io__state::di, io__state::uo) is det.
 
+:- func term_to_version_number(term(T)) = version_number is semidet.
+
+:- func term_to_timestamp(term(T)) = timestamp is semidet.
+
 %-----------------------------------------------------------------------------%
 
 :- type item_id
@@ -229,10 +231,15 @@
 
 %-----------------------------------------------------------------------------%
 
-int_to_version_number(Int) = time__int_to_time_t(Int).
+term_to_version_number(Term) = term_to_timestamp(Term).
+
+term_to_timestamp(term__functor(term__string(TimestampString), [], _)) = 
+		string_to_timestamp(TimestampString).
 
 write_version_number(VersionNumber) -->
-	io__format("%#x", [i(time__time_t_to_int(VersionNumber))]).
+	io__write_string(""""),
+	io__write_string(timestamp_to_string(VersionNumber)),
+	io__write_string("""").
 
 %-----------------------------------------------------------------------------%
 
--- recompilation_check.m	2001/05/29 04:37:40	1.3
+++ recompilation_check.m	2001/06/08 07:38:26
@@ -45,6 +45,7 @@
 :- implementation.
 
 :- import_module recompilation, recompilation_usage, recompilation_version.
+:- import_module timestamp.
 :- import_module prog_io_util, prog_util, prog_out, error_util.
 :- import_module globals, options.
 :- import_module hlds_pred.	% for field_access_function_name,
@@ -52,7 +53,7 @@
 :- import_module hlds_data.	% for type field_access_type
 
 :- import_module assoc_list, bool, exception, int, map, parser, require.
-:- import_module set, std_util, string, term, term_io, time.
+:- import_module set, std_util, string, term, term_io.
 
 recompilation_check__should_recompile(ModuleName, FindTargetFiles,
 		Info ^ modules_to_recompile, Info ^ read_modules) -->
@@ -100,7 +101,11 @@
 			{ error("recompilation_check__should_recompile_2") }
 		;
 			{ Result = exception(Exception) },
-			{ det_univ_to_type(Exception, RecompileException) },
+			{ univ_to_type(Exception, RecompileException0) ->
+				RecompileException = RecompileException0
+			;
+				rethrow(Result)
+			},
 			{ RecompileException =
 				recompile_exception(Reason, Info3) },
 			write_recompilation_message(
@@ -125,11 +130,11 @@
 	;
 		{ MaybeVersionStream = error(_) },
 		write_recompilation_message(
-			(pred(di, uo) is det -->
-				{ Reason = file_error(UsageFileName,
-						"file not found.") },
-				write_recompile_reason(ModuleName, Reason)
-			)),
+		    (pred(di, uo) is det -->
+			{ Reason = file_error(UsageFileName,
+				"file `" ++ UsageFileName ++ "' not found.") },
+			write_recompile_reason(ModuleName, Reason)
+		    )),
 		{ Info = Info1 ^ modules_to_recompile := (all) }
 	).
 
@@ -161,8 +166,11 @@
 		[]
 	;
 		io__input_stream_name(UsageFileName),
-		{ throw(recompile_exception(file_error(UsageFileName,
-			"invalid usage file version number."), Info0)) }
+		{ throw(recompile_exception(
+			file_error(UsageFileName,
+				"invalid usage file version number in file `"
+				++ UsageFileName ++ "'."),
+			Info0)) }
 	), 
 
 	%
@@ -201,7 +209,9 @@
 			)
 		->
 			throw(recompile_exception(
-				file_error(FileName, "error reading module."),
+				file_error(FileName,
+				    "error reading file `"
+				    ++ FileName ++ "'."),
 				Info0))
 		;
 			true
@@ -217,7 +227,8 @@
 		io__file_modification_time(TargetFile, TargetModTimeResult),
 		(
 			{ TargetModTimeResult = ok(TargetModTime) },
-			{ compare(TargetModTimeCompare, TargetModTime,
+			{ compare(TargetModTimeCompare,
+				time_t_to_timestamp(TargetModTime),
 				RecordedTimestamp) },
 			{ TargetModTimeCompare = (>) }
 		->
@@ -292,8 +303,7 @@
 				TimestampTerm | MaybeOtherTerms],
 		sym_name_and_args(ModuleNameTerm, ModuleName0, []),
 		SuffixTerm = term__functor(term__string(Suffix), [], _),
-		TimestampTerm = term__functor(term__integer(Timestamp),
-				[], _),
+		Timestamp = term_to_timestamp(TimestampTerm),
 		(
 			MaybeOtherTerms = [term__functor(term__atom("used"),
 						[], _)],
@@ -305,7 +315,7 @@
 	->
 		ModuleName = ModuleName0,
 		ModuleTimestamp = module_timestamp(Suffix,
-				int_to_time_t(Timestamp), NeedQualifier)
+			Timestamp, NeedQualifier)
 	;	
 		Reason = syntax_error(get_term_context(Term),
 				"error in module timestamp"),
@@ -665,14 +675,15 @@
 		Error \= no
 	->
 		throw(recompile_exception(
-			file_error(FileName, "error reading file."),
+			file_error(FileName,
+				"error reading file `" ++ FileName ++ "'."),
 			Info0))
 	;
 		Info = Info0
 	}.
 
 :- pred check_module_used_items(module_name::in, need_qualifier::in,
-	time_t::in, term::in, version_numbers::in, item_list::in,
+	timestamp::in, term::in, version_numbers::in, item_list::in,
 	recompilation_check_info::in, recompilation_check_info::out) is det.
 
 check_module_used_items(ModuleName, NeedQualifier, OldTimestamp,
@@ -815,7 +826,7 @@
 	% ambiguities with items which were used when the current
 	% module was last compiled.
 	%
-:- pred check_for_ambiguities(need_qualifier::in, time_t::in,
+:- pred check_for_ambiguities(need_qualifier::in, timestamp::in,
 	item_version_numbers::in, item_and_context::in,
 	recompilation_check_info::in, recompilation_check_info::out) is det.
 
@@ -877,7 +888,7 @@
 check_for_ambiguities(_, _, _, nothing(_) - _) --> [].
 
 :- pred check_for_pred_or_func_item_ambiguity(bool::in, need_qualifier::in,
-	time_t::in, item_version_numbers::in, pred_or_func::in,
+	timestamp::in, item_version_numbers::in, pred_or_func::in,
 	sym_name::in, list(T)::in, recompilation_check_info::in,
 	recompilation_check_info::out) is det.
 
@@ -902,7 +913,7 @@
 		[]
 	).
 
-:- pred check_for_ambiguity(need_qualifier::in, time_t::in,
+:- pred check_for_ambiguity(need_qualifier::in, timestamp::in,
 	item_version_numbers::in, item_type::in, sym_name::in,
 	arity::in, bool::out, recompilation_check_info::in,
 	recompilation_check_info::out) is det.
@@ -912,7 +923,7 @@
 	check_for_ambiguity(no, NeedQualifier, OldTimestamp, VersionNumbers,
 		ItemType, SymName, Arity, NeedsCheck). 
 
-:- pred check_for_ambiguity(bool::in, need_qualifier::in, time_t::in,
+:- pred check_for_ambiguity(bool::in, need_qualifier::in, timestamp::in,
 	item_version_numbers::in, item_type::in, sym_name::in,
 	arity::in, bool::out, recompilation_check_info::in,
 	recompilation_check_info::out) is det.
@@ -933,9 +944,7 @@
 			Name - Arity, UsedVersionNumber) },
 
 		% XXX This assumes that version numbers are timestamps.
-		{ UsedFileVersionNumber = int_to_version_number(
-				time_t_to_int(UsedFileTimestamp)) },
-		{ compare(Result, UsedVersionNumber, UsedFileVersionNumber) },
+		{ compare(Result, UsedVersionNumber, UsedFileTimestamp) },
 		{ Result = (=)
 		; Result = (<)
 		}
@@ -1336,15 +1345,15 @@
 :- pred recompile_reason_message(recompile_reason::in, maybe(context)::out,
 		list(format_component)::out) is det.
 
-recompile_reason_message(file_error(FileName, Msg), no,
-		[words(string__append(FileName, ":")), words(Msg)]).
+recompile_reason_message(file_error(_FileName, Msg), no, [words(Msg)]).
 recompile_reason_message(output_file_not_up_to_date(FileName), no,
 		[words("output file"), words(FileName),
 			words("is not up to date.")]).
 recompile_reason_message(syntax_error(Context, Msg), yes(Context),
 		[words(Msg)]).
 recompile_reason_message(module_changed(FileName), no,
-		[words(FileName), words("has changed.")]).
+		[words("file"), words("`" ++ FileName ++ "'"),
+			words("has changed.")]).
 recompile_reason_message(item_ambiguity(Item, AmbiguousItems), no, Pieces) :-
 	AmbiguousItemPieces = component_lists_to_pieces(
 		list__map(describe_item, AmbiguousItems)),
--- recompilation_usage.m	2001/05/29 04:37:40	1.3
+++ recompilation_usage.m	2001/06/04 17:58:56
@@ -78,12 +78,12 @@
 :- import_module hlds_data, hlds_pred, prog_util, type_util, (inst).
 :- import_module hlds_out, mercury_to_mercury, passes_aux, prog_data.
 :- import_module globals, options.
-:- import_module recompilation_version.
+:- import_module recompilation_version, timestamp.
 
 :- import_module assoc_list, bool, int, require.
-:- import_module queue, std_util, string, time.
+:- import_module queue, std_util, string.
 
-recompilation_usage__write_usage_file(ModuleInfo, InlineSubModules,
+recompilation_usage__write_usage_file(ModuleInfo, NestedSubModules,
 		MaybeTimestamps) -->
 	{ module_info_get_maybe_recompilation_info(ModuleInfo,
 		MaybeRecompInfo) },
@@ -102,7 +102,7 @@
 			{ FileResult = ok(Stream0) },
 			io__set_output_stream(Stream0, OldStream),
 			recompilation_usage__write_usage_file_2(ModuleInfo,
-				InlineSubModules, RecompInfo, Timestamps),
+				NestedSubModules, RecompInfo, Timestamps),
 			io__set_output_stream(OldStream, Stream),
 			io__close_output(Stream)
 		;
@@ -123,7 +123,7 @@
 		list(module_name)::in, recompilation_info::in,
 		module_timestamps::in, io__state::di, io__state::uo) is det.
 
-recompilation_usage__write_usage_file_2(ModuleInfo, InlineSubModules,
+recompilation_usage__write_usage_file_2(ModuleInfo, NestedSubModules,
 		RecompInfo, Timestamps) -->
 	io__write_int(usage_file_version_number),
 	io__write_string(","),
@@ -139,11 +139,11 @@
 	write_version_number(ThisModuleTimestamp),
 	io__write_string(").\n\n"),
 
-	( { InlineSubModules = [] } ->
+	( { NestedSubModules = [] } ->
 		io__write_string("sub_modules.\n\n")
 	;
 		io__write_string("sub_modules("),
-		io__write_list(InlineSubModules, ", ",
+		io__write_list(NestedSubModules, ", ",
 			mercury_output_bracketed_sym_name),
 		io__write_string(").\n\n")
 	),
--- recompilation_version.m	2001/05/29 04:37:40	1.2
+++ recompilation_version.m	2001/06/04 17:58:56
@@ -12,12 +12,12 @@
 
 :- interface.
 
-:- import_module recompilation, prog_data, prog_io_util.
-:- import_module io, std_util, time, term.
+:- import_module recompilation, prog_data, prog_io_util, timestamp.
+:- import_module io, std_util, term.
 
 	% recompilation_version__compute_version_numbers(SourceFileModTime,
 	%	NewItems, MaybeOldItems, VersionNumbers).
-:- pred recompilation_version__compute_version_numbers(time_t::in,
+:- pred recompilation_version__compute_version_numbers(timestamp::in,
 	item_list::in, maybe(item_list)::in, version_numbers::out) is det.
 
 :- pred recompilation_version__write_version_numbers(version_numbers::in,
@@ -67,7 +67,7 @@
 		InstanceItems, OldInstanceItems, OldInstanceVersionNumbers,
 		InstanceVersionNumbers).
 
-:- pred recompilation_version__compute_item_version_numbers(time_t::in,
+:- pred recompilation_version__compute_item_version_numbers(timestamp::in,
 	gathered_items::in, gathered_items::in,
 	item_version_numbers::in, item_version_numbers::out) is det.
 
@@ -98,7 +98,7 @@
 	    map__init
 	).
 
-:- pred recompilation_version__compute_instance_version_numbers(time_t::in,
+:- pred recompilation_version__compute_instance_version_numbers(timestamp::in,
 	instance_item_map::in, instance_item_map::in, 
 	instance_version_numbers::in, instance_version_numbers::out) is det.
 
@@ -623,11 +623,8 @@
 			[NameTerm, ArityTerm], _),
 		ParseName(NameTerm, Name),
 		ArityTerm = term__functor(term__integer(Arity), _, _),
-		VersionNumberTerm = term__functor(term__integer(VersionInt),
-			_, _)
+		VersionNumber = term_to_version_number(VersionNumberTerm)
 	->
-		VersionNumber =
-			recompilation__int_to_version_number(VersionInt),
 		Result = ok((Name - Arity) - VersionNumber)
 	;
 		Result = error("error in item version number", Term)
--- compiler_design.html	2001/06/21 09:52:51	1.1
+++ compiler_design.html	2001/06/21 09:56:26
@@ -1067,6 +1067,9 @@
   It uses the information written by recompilation_version.m and
   recompilation_usage.m to work out whether the recompilation is
   actually needed.
+
+<li> timestamp.m contains an ADT representing timestamps used
+  by smart recompilation.
 </ul>
 
 <p>
@@ -1149,6 +1152,6 @@
 <hr>
 <!---------------------------------------------------------------------------->
 
-Last update was $Date: 2001/06/21 09:52:51 $ by $Author: stayl $@cs.mu.oz.au. <br>
+Last update was $Date: 2001/05/24 06:07:33 $ by $Author: stayl $@cs.mu.oz.au. <br>
 </body>
 </html>

Index: browser/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/Mmakefile,v
retrieving revision 1.16
diff -u -u -r1.16 Mmakefile
--- Mmakefile	2001/05/18 14:23:49	1.16
+++ Mmakefile	2001/06/03 17:20:29
@@ -57,6 +57,11 @@
 		  esac							\
 		`
 
+# XXX Smart recompilation currently doesn't work when the module
+# name doesn't match the file name, so disable warnings about it
+# not working in this directory.
+MCFLAGS += --no-warn-smart-recompilation
+
 MTAGS	=	$(SCRIPTS_DIR)/mtags
 
 #-----------------------------------------------------------------------------#
--- io.m	2001/05/29 04:39:11	1.1
+++ io.m	2001/06/04 17:58:52
@@ -976,26 +976,9 @@
 	% io__file_modification_time(FileName, TimeResult)
 	% finds the last modification time of the given file.
 	% This predicate will only work on systems which provide
-	% the C library function stat(). On other systems the
+	% the POSIX C library function stat(). On other systems the
 	% returned result will always be bound to error/1.
 
-:- pred io__input_stream_file_modification_time(io__input_stream,
-		io__res(time_t), io__state, io__state).
-:- mode io__input_stream_file_modification_time(in, out, di, uo) is det.
-	% io__input_stream_file_modification_time(Stream, TimeResult)
-	% finds the last modification time of the file corresponding to
-	% the given stream. Returns an error if the stream does not
-	% correspond to a regular file.
-	% This predicate will only work on systems which provide
-	% the C library function fstat(). On other systems the
-	% returned result will always be bound to error/1.
-
-:- pred io__binary_input_stream_file_modification_time(io__binary_input_stream,
-		io__res(time_t), io__state, io__state).
-:- mode io__binary_input_stream_file_modification_time(in,
-		out, di, uo) is det.
-	% As above, but for binary input streams.
-
 %-----------------------------------------------------------------------------%
 
 % Memory management predicates.
@@ -1702,6 +1685,7 @@
 #ifdef HAVE_STAT
 	struct stat s;
 	if (stat(FileName, &s) == 0) {
+		/* XXX This assumes that a time_t will fit into an MR_Word. */
 		Time = s.st_mtime;
 		Msg = MR_string_const("""", 0);
 		Status = 1;
@@ -1720,68 +1704,6 @@
 }").
 
 :- pragma foreign_proc("MC++", io__file_modification_time_2(_FileName::in,
-		_Status::out, _Msg::out, _Time::out, _IO0::di, _IO::uo),
-		[will_not_call_mercury, thread_safe],
-"{
-	mercury::runtime::Errors::SORRY(""foreign code for this function"");
-}").
-
-io__binary_input_stream_file_modification_time(File, Result) -->
-	io__input_stream_file_modification_time(File, Result).
-
-io__input_stream_file_modification_time(File, Result) -->
-	io__input_stream_file_modification_time_2(File,
-		Status, Msg, Time),
-	{ Status = 1 ->
-		Result = ok(Time)
-	;
-		Result = error(io_error(Msg))
-	}.
-
-:- pred io__input_stream_file_modification_time_2(io__input_stream,
-		int, string, time_t, io__state, io__state).
-:- mode io__input_stream_file_modification_time_2(in,
-		out, out, out, di, uo) is det.
-
-:- pragma foreign_proc("C",
-	io__input_stream_file_modification_time_2(Stream::in,
-		Status::out, Msg::out, Time::out, IO0::di, IO::uo),
-		[will_not_call_mercury, thread_safe],
-"{
-	MercuryFile *f = (MercuryFile *) Stream;
-#if defined(HAVE_FSTAT) && \
-    (defined(HAVE_FILENO) || defined(fileno)) && \
-    defined(S_ISREG)
-	struct stat s;
-	if (MR_IS_FILE_STREAM(*f)) {
-		if (fstat(fileno(MR_file(*f)), &s) == 0 &&
-				S_ISREG(s.st_mode))
-		{
-			Time = s.st_mtime;
-			Status = 1;
-			Msg = MR_string_const("""", 0);
-		} else {
-			ML_maybe_make_err_msg(TRUE, ""fstat() failed: "",
-				MR_PROC_LABEL, Msg);
-			Status = 0;
-			Time = 0;
-		}
-	} else {
-		Msg = MR_make_string_const(
-	""io__input_stream_file_modification_time: stream not a regular file"");
-		Time = 0;
-		Status = 0;
-	}
-#else
-	Status = 0;
-	Msg = MR_make_string_const(
-""io__input_stream_file_modification_time not available on this platform"");
-#endif
-	update_io(IO0, IO);
-}").
-
-:- pragma foreign_proc("MC++",
-	io__input_stream_file_modification_time_2(_FileName::in,
 		_Status::out, _Msg::out, _Time::out, _IO0::di, _IO::uo),
 		[will_not_call_mercury, thread_safe],
 "{
--- TESTS	2001/06/04 16:33:11	1.1
+++ TESTS	2001/06/04 17:43:58
@@ -1,3 +1,6 @@
+# This is a shell script fragment to define variables containing
+# the names of the tests. This is sourced by runtests and by the
+# commands for the realclean target in the Mmakefile. 
 
 TESTS_SHOULD_SUCCEED="\
 	add_constructor_r \
--- add_constructor_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ add_constructor_r_2.err_exp.2	2001/06/08 05:32:00
@@ -1,2 +1,2 @@
 Recompiling module `add_constructor_r_2':
-  add_constructor_r_2.m has changed.
+  file `add_constructor_r_2.m' has changed.
--- add_constructor_r_2.m.2	2001/06/04 16:33:11	1.1
+++ add_constructor_r_2.m.2	2001/06/08 06:03:24
@@ -1,4 +1,3 @@
-
 :- module add_constructor_r_2.
 
 :- interface.
--- add_instance_2_r.exp.1	2001/06/04 16:33:11	1.1
+++ add_instance_2_r.exp.1	2001/06/05 11:06:34
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- add_instance_2_r.exp.2	2001/06/04 16:33:11	1.1
+++ add_instance_2_r.exp.2	2001/06/05 11:06:38
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- add_instance_2_r.m.1	2001/06/04 16:33:11	1.1
+++ add_instance_2_r.m.1	2001/06/05 11:03:30
@@ -28,5 +28,6 @@
 
 main -->
 	{ init_foo(X) },
-	output(X).
+	output(X),
+	io__nl.
 
--- add_instance_2_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ add_instance_2_r_2.err_exp.2	2001/06/08 05:32:15
@@ -1,2 +1,2 @@
 Recompiling module `add_instance_2_r_2':
-  add_instance_2_r_2.m has changed.
+  file `add_instance_2_r_2.m' has changed.
--- add_instance_r.exp.1	2001/06/04 16:33:11	1.1
+++ add_instance_r.exp.1	2001/06/05 11:06:27
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- add_instance_r.exp.2	2001/06/04 16:33:11	1.1
+++ add_instance_r.exp.2	2001/06/05 11:06:31
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- add_instance_r.m.1	2001/06/04 16:33:11	1.1
+++ add_instance_r.m.1	2001/06/05 11:03:52
@@ -12,5 +12,6 @@
 
 main -->
 	{ init_foo(X) },
-	output(X).
+	output(X),
+	io__nl.
 
--- add_instance_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ add_instance_r_2.err_exp.2	2001/06/08 05:32:07
@@ -1,2 +1,2 @@
 Recompiling module `add_instance_r_2':
-  add_instance_r_2.m has changed.
+  file `add_instance_r_2.m' has changed.
--- add_type_nr_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ add_type_nr_2.err_exp.2	2001/06/08 05:32:22
@@ -1,2 +1,2 @@
 Recompiling module `add_type_nr_2':
-  add_type_nr_2.m has changed.
+  file `add_type_nr_2.m' has changed.
--- add_type_re_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ add_type_re_2.err_exp.2	2001/06/08 05:33:57
@@ -1,2 +1,2 @@
 Recompiling module `add_type_re_2':
-  add_type_re_2.used: file not found.
+  file `add_type_re_2.used' not found.
--- change_class_r.exp.1	2001/06/04 16:33:11	1.1
+++ change_class_r.exp.1	2001/06/05 11:06:49
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- change_class_r.exp.2	2001/06/04 16:33:11	1.1
+++ change_class_r.exp.2	2001/06/05 11:06:53
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- change_class_r.m.1	2001/06/04 16:33:11	1.1
+++ change_class_r.m.1	2001/06/05 11:04:10
@@ -12,5 +12,6 @@
 
 main -->
 	{ init_foo(X) },
-	output(X).
+	output(X),
+	io__nl.
 
--- change_class_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ change_class_r_2.err_exp.2	2001/06/08 05:32:30
@@ -1,2 +1,2 @@
 Recompiling module `change_class_r_2':
-  change_class_r_2.m has changed.
+  file `change_class_r_2.m' has changed.
--- change_instance_r.exp.1	2001/06/04 16:33:11	1.1
+++ change_instance_r.exp.1	2001/06/05 11:06:57
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- change_instance_r.exp.2	2001/06/04 16:33:11	1.1
+++ change_instance_r.exp.2	2001/06/05 11:07:01
@@ -1 +1 @@
-a
\ No newline at end of file
+a
--- change_instance_r.m.1	2001/06/04 16:33:11	1.1
+++ change_instance_r.m.1	2001/06/05 11:04:25
@@ -28,5 +28,6 @@
 
 main -->
 	{ init_foo(X) },
-	output(X).
+	output(X),
+	io__nl.
 
--- change_instance_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ change_instance_r_2.err_exp.2	2001/06/08 05:32:37
@@ -1,2 +1,2 @@
 Recompiling module `change_instance_r_2':
-  change_instance_r_2.m has changed.
+  file `change_instance_r_2.m' has changed.
--- change_mode_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ change_mode_r_2.err_exp.2	2001/06/08 05:32:45
@@ -1,2 +1,2 @@
 Recompiling module `change_mode_r_2':
-  change_mode_r_2.m has changed.
+  file `change_mode_r_2.m' has changed.
--- field_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ field_r_2.err_exp.2	2001/06/08 05:32:52
@@ -1,2 +1,2 @@
 Recompiling module `field_r_2':
-  field_r_2.m has changed.
+  file `field_r_2.m' has changed.
--- func_overloading_nr_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ func_overloading_nr_2.err_exp.2	2001/06/08 05:32:59
@@ -1,2 +1,2 @@
 Recompiling module `func_overloading_nr_2':
-  func_overloading_nr_2.m has changed.
+  file `func_overloading_nr_2.m' has changed.
--- func_overloading_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ func_overloading_r_2.err_exp.2	2001/06/08 05:33:06
@@ -1,2 +1,2 @@
 Recompiling module `func_overloading_r_2':
-  func_overloading_r_2.m has changed.
+  file `func_overloading_r_2.m' has changed.
--- lambda_mode_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ lambda_mode_r_2.err_exp.2	2001/06/08 05:33:14
@@ -1,2 +1,2 @@
 Recompiling module `lambda_mode_r_2':
-  lambda_mode_r_2.m has changed.
+  file `lambda_mode_r_2.m' has changed.
--- nested_module_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ nested_module_r_2.err_exp.2	2001/06/08 05:33:22
@@ -1,2 +1,2 @@
 Recompiling module `nested_module_r_2':
-  nested_module_r_2.m has changed.
+  file `nested_module_r_2.m' has changed.
--- no_version_numbers_r.err_exp.2	2001/06/04 16:33:11	1.1
+++ no_version_numbers_r.err_exp.2	2001/06/08 05:33:29
@@ -1,2 +1,2 @@
 Recompiling module `no_version_numbers_r':
-  no_version_numbers_r_2.int has changed.
+  file `no_version_numbers_r_2.int' has changed.
--- pragma_type_spec_r.exp.1	2001/06/04 16:33:11	1.1
+++ pragma_type_spec_r.exp.1	2001/06/05 11:07:57
@@ -1 +1 @@
-[1, 2, 3, 4, 5, 6]
\ No newline at end of file
+[1, 2, 3, 4, 5, 6]
--- pragma_type_spec_r.exp.2	2001/06/04 16:33:11	1.1
+++ pragma_type_spec_r.exp.2	2001/06/05 11:08:01
@@ -1 +1 @@
-[1, 2, 3, 4, 5, 6]
\ No newline at end of file
+[1, 2, 3, 4, 5, 6]
--- pragma_type_spec_r.m.1	2001/06/04 16:33:11	1.1
+++ pragma_type_spec_r.m.1	2001/06/05 11:04:40
@@ -12,5 +12,6 @@
 
 main -->
 	{ List = f([1, 2, 3], [4, 5, 6]) },
-	io__write(List).
+	io__write(List),
+	io__nl.
 
--- pragma_type_spec_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ pragma_type_spec_r_2.err_exp.2	2001/06/08 05:33:37
@@ -1,2 +1,2 @@
 Recompiling module `pragma_type_spec_r_2':
-  pragma_type_spec_r_2.m has changed.
+  file `pragma_type_spec_r_2.m' has changed.
--- pred_ctor_ambiguity_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ pred_ctor_ambiguity_r_2.err_exp.2	2001/06/08 05:33:44
@@ -1,2 +1,2 @@
 Recompiling module `pred_ctor_ambiguity_r_2':
-  pred_ctor_ambiguity_r_2.m has changed.
+  file `pred_ctor_ambiguity_r_2.m' has changed.
--- pred_overloading_r_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ pred_overloading_r_2.err_exp.2	2001/06/08 05:33:52
@@ -1,2 +1,2 @@
 Recompiling module `pred_overloading_r_2':
-  pred_overloading_r_2.m has changed.
+  file `pred_overloading_r_2.m' has changed.
--- remove_type_re_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ remove_type_re_2.err_exp.2	2001/06/08 05:34:03
@@ -1,2 +1,2 @@
 Recompiling module `remove_type_re_2':
-  remove_type_re_2.used: file not found.
+  file `remove_type_re_2.used' not found.
--- runtests	2001/06/04 16:33:11	1.1
+++ runtests	2001/06/05 11:01:39
@@ -11,7 +11,12 @@
 failing_tests=""
 cleanup=true
 
-export generate_missing_exp_files cleanup
+# If the compilation is supposed to fail then the mmake
+# output should be suppressed to avoid making it harder
+# to find genuine failures in the nightly test logs.
+failing_make_output=failing_make_output
+
+export mmakeopts generate_missing_exp_files cleanup failing_make_output
 
 run_all_tests () {
 	test_should_fail=$1
@@ -40,6 +45,7 @@
 	echo "mmakeopts=$mmakeopts"
 	rm -f .allres
 	case $cleanup in true)
+		rm -f $failing_make_output
 		. ../shutdown ;;
 	esac
 	exit 0
--- test_functions	2001/06/04 16:33:11	1.1
+++ test_functions	2001/06/05 16:53:34
@@ -19,27 +19,28 @@
 
 	for module in $modules
 	do
-		cp -f $module.m.1 $module.m
+		rm -f $module.m
+		cp $module.m.1 $module.m
 
 		# The module.m.<n> files are the only ones
 		# that should be edited.
 		chmod -w $module.m
-	
-		# XXX Avoid producing output files with the same timestamp
-		# as the input source file. The up-to-date check for the output
-		# file in recompilation_check.m checks that the output file's
-		# timestamp is strictly greater than the input file's, so it
-		# will recompile if they are the same.
-		#
-		# This won't be a problem in practice, unless for some reason
-		# a user decides to have mmake invoked by their editor
-		# automatically after each edit. If a file takes less
-		# than a second to compile, recompiling it all the time
-		# won't be noticeable. The recompilation will affect
-		# the `--verbose-recompilation' messages, so we need to
-		# avoid it here.
-		sleep 1
 	done
+
+	# XXX Avoid producing output files with the same timestamp
+	# as the input source file. The up-to-date check for the output
+	# file in recompilation_check.m checks that the output file's
+	# timestamp is strictly greater than the input file's, so it
+	# will recompile if they are the same.
+	#
+	# This won't be a problem in practice, unless for some reason
+	# a user decides to have mmake invoked by their editor
+	# automatically after each edit. If a file takes less
+	# than a second to compile, recompiling it all the time
+	# won't be noticeable. The recompilation will affect
+	# the `--verbose-recompilation' messages, so we need to
+	# avoid it here.
+	sleep 1
 }
 
 #
@@ -55,19 +56,21 @@
 	module=$1
 	module_version=$2
 
+	# GNU make only considers a file out of date if a dependency's
+	# timestamp is strictly greater than the file's timestamp.
+	# We need to make sure that the `.c' file is out of date with
+	# respect to the `.m' file.
+	sleep 1
+
 	cp -f $module.m.$module_version $module.m
 	chmod -w $module.m
 
+	# See comment in test_module().
 	sleep 1
 }
 
 mmake_depend () {
-	if mmake $main_module.depend
-	then
-		:
-	else 
-		exit 1
-	fi
+	eval mmake $mmakeopts $main_module.depend || exit 1
 }
 
 #
@@ -79,7 +82,7 @@
 compare_files () {
 	if [ $# != 2 ]
 	then
-		echo "usage: compare_files expected_file result_file"
+		echo "** usage: compare_files expected_file result_file"
 		exit 1
 	fi
 	
@@ -88,19 +91,21 @@
 
 	if [ -f $exp_file ]
 	then
-		if diff -c $exp_file $res_file >> $main_module.res
+		if diff ${DIFF_OPTS-"-c"} $exp_file \
+				$res_file >> $main_module.res
 		then
 			:
 		else
+			echo "** Error: $exp_file and $res_file differ."
 			exit 1
 		fi
 	else
 		if [ $generate_missing_exp_files = true ]
 		then
-			echo "WARNING: generating $exp_file"
+			echo "** WARNING: generating $exp_file"
 			cp $res_file $exp_file
 		else
-			echo "Error: $exp_file not found"
+			echo "** Error: $exp_file not found"
 			exit 1
 		fi
 	fi
@@ -112,7 +117,7 @@
 mmake_test () {
 	if [ $# != 2 ]
 	then
-		echo "usage: mmake_test output_file_version should_fail"
+		echo "** usage: mmake_test output_file_version should_fail"
 		exit 1
 	fi
 
@@ -126,10 +131,10 @@
 		# output should be suppressed to avoid making it harder
 		# to find genuine failures in the nightly test logs.
 		#
-		mmake $main_module > /dev/null 2>&1
+		eval mmake $mmakeopts $main_module > $failing_make_output 2>&1
 		;;
 	    false)
-		mmake $main_module
+		eval mmake $mmakeopts $main_module
 		;;
 	esac
 
@@ -138,7 +143,7 @@
 		case $mmake_should_fail in
 		    true)
 			echo \
-		"Error: mmake $main_module succeeded where it should fail"
+	"** Error: mmake $mmakeopts $main_module succeeded where it should fail"
 			exit 1
 			;;
 		esac
@@ -150,7 +155,7 @@
 	    *)
 		case $mmake_should_fail in
 		    false)
-			echo "Error: mmake $main_module failed"
+			echo "** Error: mmake $mmakeopts $main_module failed"
 			exit 1
 			;;
 		esac
@@ -161,7 +166,7 @@
 check_err_file () {
 	if [ $# != 2 ]
 	then	
-		echo "usage: check_err_file module message_file_version"
+		echo "** usage: check_err_file module message_file_version"
 	fi
 
 	module=$1
@@ -173,7 +178,7 @@
 cleanup_test () {
 	case $cleanup in
 	true)
-		mmake $main_module.realclean
+		eval mmake $mmakeopts $main_module.realclean
 
 		for module in $modules
 		do
--- two_module_test	2001/06/04 16:33:11	1.1
+++ two_module_test	2001/06/05 10:45:23
@@ -7,7 +7,7 @@
 
 if [ $# != 3 ]
 then
-	echo "usage: two_module_test test_should_fail module1 module2"
+	echo "** usage: two_module_test test_should_fail module1 module2"
 	exit 1
 fi
 
--- type_qual_re_2.err_exp.2	2001/06/04 16:33:11	1.1
+++ type_qual_re_2.err_exp.2	2001/06/08 05:34:09
@@ -1,2 +1,2 @@
 Recompiling module `type_qual_re_2':
-  type_qual_re_2.used: file not found.
+  file `type_qual_re_2.used' not found.
--------------------------------------------------------------------------
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