[m-rev.] for review: unnecessary recompilations with intermodule analysis

Peter Wang novalazy at gmail.com
Thu May 29 11:17:18 AEST 2008


Branches: main

The `--intermodule-analysis' option was broken in that touching a `.m' file
would cause its `.analysis' file to be remade (correct) but then all the
target code files which depend on that `.analysis' file would be remade,
even if the `.analysis' file should be unchanged.

Fix that by making analysis files work like other interface files: the
timestamp on the `.analysis' file reflects the last time it was changed, and
the `.analysis_date' file reflects the last time the module was analysed.

To that end we need to move the module status out of the `.analysis' file into
a corresponding `.analysis_status' file.  Then analysing other modules will
only touch the `.analysis_status' file.  `.analysis_status' are not installed.

compiler/analysis.m:
compiler/analysis.file.m:
	Separate predicates for reading/writing the module status from the
	module analysis results proper.

	Use the usual technique of writing analysis results to `.analysis.tmp'
	and only updating the `.analysis' file if its changed.

	Write analysis results for a single function-id in sorted order to
	remove spurious differences.

	Make use some standard interface file handling predicates.

compiler/make.util.m:
	Simplify the special treatment of timestamps for `.analysis' files.

compiler/make.module_target.m:
compiler/make.program_target.m:
	Conform to interface changes.

Index: compiler/analysis.file.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/analysis.file.m,v
retrieving revision 1.3
diff -u -b -r1.3 analysis.file.m
--- compiler/analysis.file.m	27 Mar 2008 02:29:40 -0000	1.3
+++ compiler/analysis.file.m	29 May 2008 01:13:48 -0000
@@ -9,42 +9,46 @@
 % File: analysis.file.m
 % Main author: stayl, wangp.
 %
-% An analysis file contains analysis results for a single module.
+% This module deals with the on-disk representations of the analysis registry
+% and associated files.
 %
 %-----------------------------------------------------------------------------%
 
 :- module analysis.file.
-
 :- interface.
 
     % read_module_overall_status(Compiler, ModuleName, MaybeModuleStatus, !IO)
     %
-    % Attempt to read the overall status from a module `.analysis' file.
+    % Read the overall status of a module from its `.analysis_status' file.
     % If the module has outstanding requests, then an overall status of
     % `optimal' is downgraded to `suboptimal'.
     %
 :- pred read_module_overall_status(Compiler::in, module_name::in,
-    maybe(analysis_status)::out, io::di, io::uo) is det <= compiler(Compiler).
+    analysis_status::out, io::di, io::uo) is det <= compiler(Compiler).
+
+    % write_module_overall_status(AnalysisInfo, ModuleName, ModuleStatus, !IO)
+    %
+    % Write the status of a module to its `.analysis_status' file.
+    %
+:- pred write_module_overall_status(analysis_info::in, module_name::in,
+    analysis_status::in, io::di, io::uo) is det.
 
-    % read_module_analysis_results(AnalysisInfo, ModuleName,
-    %   OverallStatus, AnalysisResults, !IO)
+    % read_module_analysis_results(AnalysisInfo, ModuleName, AnalysisResults,
+    %   !IO)
     %
-    % Read the overall module status and analysis results from a `.analysis'
-    % file.
+    % Read the analysis results from a `.analysis' file.
     %
 :- pred read_module_analysis_results(analysis_info::in, module_name::in,
-    analysis_status::out, module_analysis_map(some_analysis_result)::out,
-    io::di, io::uo) is det.
+    module_analysis_map(some_analysis_result)::out, io::di, io::uo) is det.
 
-    % write_module_analysis_results(AnalysisInfo, ModuleName,
-    %   OverallStatus, AnalysisResults, !IO)
+    % write_module_analysis_results(AnalysisInfo, ModuleName, AnalysisResults,
+    %   !IO)
     %
-    % Write the overall module status and analysis results to a `.analysis'
-    % file.
+    % Write the analysis results for a module to its `.analysis' file.
     %
 :- pred write_module_analysis_results(analysis_info::in,
-    module_name::in, analysis_status::in,
-    module_analysis_map(some_analysis_result)::in, io::di, io::uo) is det.
+    module_name::in, module_analysis_map(some_analysis_result)::in,
+    io::di, io::uo) is det.
 
     % read_module_analysis_requests(AnalysisInfo, ModuleName, ModuleRequests,
     %   !IO)
@@ -88,27 +92,38 @@
     io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
 
 :- implementation.
 
+:- import_module libs.compiler_util.
+:- import_module parse_tree.            % XXX unwanted dependency
+:- import_module parse_tree.modules.    % XXX unwanted dependency
+
 :- import_module bool.
+:- import_module char.
 :- import_module exception.
 :- import_module parser.
 :- import_module term.
 :- import_module term_io.
 :- import_module varset.
 
-:- import_module libs.compiler_util.
-
 %-----------------------------------------------------------------------------%
 
 % The format of an analysis result file is:
 %
 % version_number.
-% module_status.
 % analysis_name(analysis_version, func_id, call_pattern, answer_pattern,
 %   result_status).
 
+% An .analysis_status file contains a single line, which is one of:
+%
+% optimal.  
+% suboptimal.
+% invalid.
+%
+% A missing file is equivalent to `optimal'.
+
 % The format of an IMDG file is:
 %
 % version_number.
@@ -124,12 +139,16 @@
 
 :- func version_number = int.
 
-version_number = 3.
+version_number = 4.
 
 :- func analysis_registry_suffix = string.
 
 analysis_registry_suffix = ".analysis".
 
+:- func analysis_registry_status_suffix = string.
+
+analysis_registry_status_suffix = ".analysis_status".
+
 :- func imdg_suffix = string.
 
 imdg_suffix = ".imdg".
@@ -140,70 +159,99 @@
 
 %-----------------------------------------------------------------------------%
 
-read_module_overall_status(Compiler, ModuleName, MaybeModuleStatus, !IO) :-
-    module_name_to_read_file_name(Compiler, ModuleName, analysis_registry_suffix,
-        MaybeAnalysisFileName, !IO),
+read_module_overall_status(Compiler, ModuleName, ModuleStatus, !IO) :-
+    module_name_to_read_file_name(Compiler, ModuleName,
+        analysis_registry_status_suffix, MaybeFileName, !IO),
     (
-        MaybeAnalysisFileName = ok(AnalysisFileName),
-        read_module_overall_status_2(AnalysisFileName, MaybeModuleStatus0,
-            !IO),
-        ( MaybeModuleStatus0 = yes(optimal) ->
+        MaybeFileName = ok(FileName),
+        read_module_overall_status_2(FileName, ModuleStatus0, !IO)
+    ;
+        MaybeFileName = error(_),
+        % Missing file means optimal.  We don't install `.analysis_status'
+        % files when installing libraries, for example.
+        ModuleStatus0 = optimal
+    ),
+    (
+        ModuleStatus0 = optimal,
             module_name_to_read_file_name(Compiler, ModuleName, request_suffix,
                 MaybeRequestFileName, !IO),
             (
                 % There are outstanding requests for this module.
                 MaybeRequestFileName = ok(_),
-                MaybeModuleStatus = yes(suboptimal)
+            ModuleStatus = suboptimal
             ;
                 MaybeRequestFileName = error(_),
-                MaybeModuleStatus = MaybeModuleStatus0
-            )
-        ;
-            MaybeModuleStatus = MaybeModuleStatus0
+            ModuleStatus = ModuleStatus0
         )
     ;
-        MaybeAnalysisFileName = error(_),
-        MaybeModuleStatus = no
+        ( ModuleStatus0 = suboptimal
+        ; ModuleStatus0 = invalid
+        ),
+        ModuleStatus = ModuleStatus0
     ).
 
-:- pred read_module_overall_status_2(string::in, maybe(analysis_status)::out,
+:- pred read_module_overall_status_2(string::in, analysis_status::out,
     io::di, io::uo) is det.
 
-read_module_overall_status_2(AnalysisFileName, MaybeModuleStatus, !IO) :-
-    io.open_input(AnalysisFileName, OpenResult, !IO),
+read_module_overall_status_2(FileName, ModuleStatus, !IO) :-
+    io.open_input(FileName, OpenResult, !IO),
     (
         OpenResult = ok(Stream),
-        io.set_input_stream(Stream, OldStream, !IO),
+        io.read_line_as_string(Stream, ReadResult, !IO),
+        io.close_input(Stream, !IO),
+        (
+            ReadResult = ok(String),
+            ( string.prefix(String, "optimal.") ->
+                ModuleStatus = optimal
+            ; string.prefix(String, "suboptimal.") ->
+                ModuleStatus = suboptimal
+            ; string.prefix(String, "invalid.") ->
+                ModuleStatus = invalid
+            ;
+                unexpected(this_file,
+                    "read_module_overall_status_2: unexpected line")
+            )
+        ;
+            ReadResult = eof,
+            unexpected(this_file,
+                "read_module_overall_status_2: unexpected eof")
+        ;
+            ReadResult = error(IOError),
+            unexpected(this_file,
+                "read_module_overall_status_2: " ++ io.error_message(IOError))
+        )
+    ;
+        OpenResult = error(IOError),
+        unexpected(this_file,
+            "read_module_overall_status_2: " ++ io.error_message(IOError))
+    ).
 
-        promise_only_solution_io(
-            (pred(Status::out, !.IO::di, !:IO::uo) is cc_multi :-
-                try_io((pred(Status0::out, !.IO::di, !:IO::uo) is det :-
-                    check_analysis_file_version_number(!IO),
-                    read_module_status(Status0, !IO)
-                ), Status, !IO)
-            ), Result, !IO),
+write_module_overall_status(Info, ModuleName, Status, !IO) :-
+    module_name_to_write_file_name(Info ^ compiler, ModuleName,
+        analysis_registry_status_suffix, FileName, !IO),
+    io.open_output(FileName, OpenResult, !IO),
         (
-            Result = succeeded(ModuleStatus),
-            MaybeModuleStatus = yes(ModuleStatus)
+        OpenResult = ok(Stream),
+        (
+            Status = optimal,
+            io.write_string(Stream, "optimal.\n", !IO)
         ;
-            Result = failed,
-            MaybeModuleStatus = no
+            Status = suboptimal,
+            io.write_string(Stream, "suboptimal.\n", !IO)
         ;
-            Result = exception(_),
-            % XXX Report error.
-            MaybeModuleStatus = no
+            Status = invalid,
+            io.write_string(Stream, "invalid.\n", !IO)
         ),
-        io.set_input_stream(OldStream, _, !IO),
-        io.close_input(Stream, !IO)
+        io.close_output(Stream, !IO)
     ;
-        OpenResult = error(_),
-        MaybeModuleStatus = no
+        OpenResult = error(IOError),
+        unexpected(this_file,
+            "write_module_overall_status: " ++ io.error_message(IOError))
     ).
 
 %-----------------------------------------------------------------------------%
 
-read_module_analysis_results(Info, ModuleName, ModuleStatus, ModuleResults,
-        !IO) :-
+read_module_analysis_results(Info, ModuleName, ModuleResults, !IO) :-
     % If the module's overall status is `invalid' then at least one of its
     % results is invalid.  However, we can't just discard the results as we
     % want to know which results change after we reanalyse the module.
@@ -213,19 +261,18 @@
     (
         MaybeAnalysisFileName = ok(AnalysisFileName),
         read_module_analysis_results_2(Compiler, AnalysisFileName,
-            ModuleStatus, ModuleResults, !IO)
+            ModuleResults, !IO)
     ;
         MaybeAnalysisFileName = error(_),
-        ModuleStatus = optimal,
         ModuleResults = map.init
     ).
 
 :- pred read_module_analysis_results_2(Compiler::in, string::in,
-    analysis_status::out, module_analysis_map(some_analysis_result)::out,
-    io::di, io::uo) is det <= compiler(Compiler).
+    module_analysis_map(some_analysis_result)::out, io::di, io::uo) is det
+    <= compiler(Compiler).
 
-read_module_analysis_results_2(Compiler, AnalysisFileName,
-        ModuleStatus, ModuleResults, !IO) :-
+read_module_analysis_results_2(Compiler, AnalysisFileName, ModuleResults,
+        !IO) :-
     ModuleResults0 = map.init,
     io.open_input(AnalysisFileName, OpenResult, !IO),
     (
@@ -238,7 +285,6 @@
         io.set_input_stream(Stream, OldStream, !IO),
 
         check_analysis_file_version_number(!IO),
-        read_module_status(ModuleStatus, !IO),
         promise_only_solution_io(
             (pred(Results2::out, !.IO::di, !:IO::uo) is cc_multi :-
                 try_io((pred(Results1::out, !.IO::di, !:IO::uo) is det :-
@@ -265,26 +311,9 @@
             io.write_string(AnalysisFileName, !IO),
             io.nl(!IO)
         ), !IO),
-        ModuleStatus = optimal,
         ModuleResults = ModuleResults0
     ).
 
-:- pred read_module_status(analysis_status::out, io::di, io::uo) is det.
-
-read_module_status(Status, !IO) :-
-    parser.read_term(TermResult : read_term, !IO),
-    ( TermResult = term(_, term.functor(term.atom(String), [], _)) ->
-        ( analysis_status_to_string(Status0, String) ->
-            Status = Status0
-        ;
-            Msg = "expected analysis status: " ++ String,
-            throw(invalid_analysis_file(Msg))
-        )
-    ;
-        Msg = "parser.read_term: " ++ string(TermResult),
-        throw(invalid_analysis_file(Msg))
-    ).
-
 :- pred analysis_status_to_string(analysis_status, string).
 :- mode analysis_status_to_string(in, out) is det.
 :- mode analysis_status_to_string(out, in) is semidet.
@@ -446,9 +475,6 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type read_analysis_header(T) == pred(T, io, io).
-:- inst read_analysis_header == (pred(out, di, uo) is det).
-
 :- type parse_entry(T) == pred(term, T, T).
 :- inst parse_entry == (pred(in, in, out) is det).
 
@@ -555,24 +581,16 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-write_module_analysis_results(Info, ModuleName, ModuleStatus, ModuleResults,
-        !IO) :-
+write_module_analysis_results(Info, ModuleName, ModuleResults, !IO) :-
     debug_msg((pred(!.IO::di, !:IO::uo) is det :-
         io.write_string("% Writing module analysis results for ", !IO),
         io.write(ModuleName, !IO),
         io.nl(!IO)
     ), !IO),
-    WriteHeader = write_module_status(ModuleStatus),
-    write_analysis_file(Info ^ compiler,
-        ModuleName, analysis_registry_suffix,
-        WriteHeader, write_result_entry, ModuleResults, !IO).
-
-:- pred write_module_status(analysis_status::in, io::di, io::uo) is det.
-
-write_module_status(Status, !IO) :-
-    term_io.write_term_nl(init:varset, Term, !IO),
-    Term = functor(atom(String), [], context_init),
-    analysis_status_to_string(Status, String).
+    ToTmp = yes,
+    write_analysis_file(Info ^ compiler, ModuleName, analysis_registry_suffix,
+        ToTmp, write_result_entry, ModuleResults, FileName, !IO),
+    update_interface(FileName, !IO).
 
 :- pred write_result_entry
     `with_type` write_entry(some_analysis_result)
@@ -620,7 +638,7 @@
             (
                 AppendResult = ok(AppendStream),
                 io.set_output_stream(AppendStream, OldOutputStream, !IO),
-                write_analysis_entries(write_request_entry(Compiler),
+                write_analysis_file_2(write_request_entry(Compiler),
                     ModuleRequests, !IO),
                 io.set_output_stream(OldOutputStream, _, !IO),
                 io.close_output(AppendStream, !IO),
@@ -638,8 +656,8 @@
     ),
     (
         Appended = no,
-        write_analysis_file(AnalysisFileName, nop,
-            write_request_entry(Compiler), ModuleRequests, !IO)
+        write_analysis_file(AnalysisFileName, write_request_entry(Compiler),
+            ModuleRequests, !IO)
     ;
         Appended = yes
     ).
@@ -669,8 +687,9 @@
 %-----------------------------------------------------------------------------%
 
 write_module_imdg(Info, ModuleName, ModuleEntries, !IO) :-
-    write_analysis_file(Info ^ compiler, ModuleName, imdg_suffix, nop,
-        write_imdg_arc(Info ^ compiler), ModuleEntries, !IO).
+    ToTmp = no,
+    write_analysis_file(Info ^ compiler, ModuleName, imdg_suffix, ToTmp,
+        write_imdg_arc(Info ^ compiler), ModuleEntries, _FileName, !IO).
 
 :- pred write_imdg_arc(Compiler::in)
     `with_type` write_entry(imdg_arc)
@@ -700,65 +719,67 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type write_header == pred(io, io).
-:- inst write_header == (pred(di, uo) is det).
-
 :- type write_entry(T) == pred(analysis_name, func_id, T, io, io).
 :- inst write_entry == (pred(in, in, in, di, uo) is det).
 
 :- pred write_analysis_file(Compiler::in, module_name::in, string::in,
-    write_header::in(write_header),
-    write_entry(T)::in(write_entry), module_analysis_map(T)::in,
-    io::di, io::uo) is det <= compiler(Compiler).
-
-write_analysis_file(Compiler, ModuleName, Suffix, WriteHeader, WriteEntry,
-        ModuleResults, !IO) :-
-    module_name_to_write_file_name(Compiler, ModuleName, Suffix,
-        AnalysisFileName, !IO),
-    write_analysis_file(AnalysisFileName, WriteHeader, WriteEntry,
-        ModuleResults, !IO).
+    bool::in, write_entry(T)::in(write_entry), module_analysis_map(T)::in,
+    string::out, io::di, io::uo) is det <= compiler(Compiler).
 
-:- pred write_analysis_file(string::in, write_header::in(write_header),
-    write_entry(T)::in(write_entry), module_analysis_map(T)::in,
-    io::di, io::uo) is det.
+write_analysis_file(Compiler, ModuleName, Suffix, ToTmp, WriteEntry,
+        ModuleResults, FileName, !IO) :-
+    module_name_to_write_file_name(Compiler, ModuleName, Suffix, FileName,
+        !IO),
+    (
+        ToTmp = yes,
+        WriteFileName = FileName ++ ".tmp"
+    ;
+        ToTmp = no,
+        WriteFileName = FileName
+    ),
+    write_analysis_file(WriteFileName, WriteEntry, ModuleResults, !IO).
 
-write_analysis_file(AnalysisFileName, WriteHeader, WriteEntry, ModuleResults,
-        !IO) :-
-    io.open_output(AnalysisFileName, OpenResult, !IO),
+:- pred write_analysis_file(string::in, write_entry(T)::in(write_entry),
+    module_analysis_map(T)::in, io::di, io::uo) is det.
+
+write_analysis_file(FileName, WriteEntry, ModuleResults, !IO) :-
+    io.open_output(FileName, OpenResult, !IO),
     (
         OpenResult = ok(Stream),
         io.set_output_stream(Stream, OldOutput, !IO),
         io.write_int(version_number, !IO),
         io.write_string(".\n", !IO),
-        WriteHeader(!IO),
-        write_analysis_entries(WriteEntry, ModuleResults, !IO),
+        write_analysis_file_2(WriteEntry, ModuleResults, !IO),
         io.set_output_stream(OldOutput, _, !IO),
         io.close_output(Stream, !IO)
     ;
-        OpenResult = error(Msg),
-        io.write_string("Error opening ", !IO),
-        io.write_string(AnalysisFileName, !IO),
-        io.write_string(" for output: ", !IO),
-        io.write_string(io.error_message(Msg), !IO),
-        io.nl(!IO)
+        OpenResult = error(IOError),
+        unexpected(this_file, "write_analysis_file: error opening `" ++
+            FileName ++ "' for output: " ++ io.error_message(IOError))
     ).
 
-:- pred write_analysis_entries(write_entry(T)::in(write_entry),
+:- pred write_analysis_file_2(write_entry(T)::in(write_entry),
     module_analysis_map(T)::in, io::di, io::uo) is det.
 
-write_analysis_entries(WriteEntry, ModuleResults, !IO) :-
-    map.foldl(
-        (pred(AnalysisName::in, FuncResults::in, di, uo) is det -->
-            map.foldl(
-                (pred(FuncId::in, FuncResultList::in, di, uo) is det -->
+write_analysis_file_2(WriteEntry, ModuleResults, !IO) :-
+    map.foldl(write_analysis_file_3(WriteEntry), ModuleResults, !IO).
+
+:- pred write_analysis_file_3(write_entry(T)::in(write_entry), string::in,
+    func_analysis_map(T)::in, io::di, io::uo) is det.
+
+write_analysis_file_3(WriteEntry, AnalysisName, FuncResults, !IO) :-
+    map.foldl(write_analysis_file_4(WriteEntry, AnalysisName),
+        FuncResults, !IO).
+
+:- pred write_analysis_file_4(write_entry(T)::in(write_entry), string::in,
+    func_id::in, list(T)::in, io::di, io::uo) is det.
+
+write_analysis_file_4(WriteEntry, AnalysisName, FuncId, FuncResultList, !IO) :-
+    list.sort(FuncResultList, FuncResultListSorted),
                     list.foldl(
-                        (pred(FuncResult::in, di, uo) is det -->
-                            WriteEntry(AnalysisName, FuncId, FuncResult)
-                        ), FuncResultList)
-                ),
-                FuncResults)
-        ),
-        ModuleResults, !IO).
+        (pred(FuncResult::in, !.IO::di, !:IO::uo) is det :-
+            WriteEntry(AnalysisName, FuncId, FuncResult, !IO)
+        ), FuncResultListSorted, !IO).
 
 %-----------------------------------------------------------------------------%
 
@@ -773,11 +794,5 @@
     io.remove_file(RequestFileName, _, !IO).
 
 %-----------------------------------------------------------------------------%
-
-:- pred nop(io::di, io::uo) is det.
-
-nop(!IO).
-
-%-----------------------------------------------------------------------------%
 :- end_module analysis.file.
 %-----------------------------------------------------------------------------%
Index: compiler/analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/analysis.m,v
retrieving revision 1.4
diff -u -b -r1.4 analysis.m
--- compiler/analysis.m	28 May 2008 00:52:27 -0000	1.4
+++ compiler/analysis.m	29 May 2008 01:13:48 -0000
@@ -279,7 +279,7 @@
     % Attempt to read the overall status from a module `.analysis' file.
     %
 :- pred read_module_overall_status(Compiler::in, module_name::in,
-    maybe(analysis_status)::out, io::di, io::uo) is det
+    analysis_status::out, io::di, io::uo) is det
     <= compiler(Compiler).
 
 :- pred enable_debug_messages(bool::in, io::di, io::uo) is det.
@@ -294,6 +294,8 @@
 :- import_module analysis.file.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module parse_tree.            % XXX unwanted dependency
+:- import_module parse_tree.modules.    % XXX unwanted dependency
 
 :- import_module map.
 :- import_module string.
@@ -1002,8 +1004,9 @@
         % sanity check
         map.lookup(!.Info ^ module_statuses, ModuleName, _StatusMustExist)
     ;
-        read_module_analysis_results(!.Info, ModuleName,
-            ModuleStatus, ModuleResults, !IO),
+        analysis.read_module_overall_status(!.Info ^ compiler, ModuleName,
+            ModuleStatus, !IO),
+        read_module_analysis_results(!.Info, ModuleName, ModuleResults, !IO),
         !Info ^ module_statuses ^ elem(ModuleName) := ModuleStatus,
         !Info ^ old_analysis_results ^ elem(ModuleName) := ModuleResults
     ).
@@ -1039,7 +1042,7 @@
         !Info, !IO) :-
     % The current module was just compiled so we set its status to the
     % lub of all the new analysis results generated.
-    ( NewResults = !.Info ^ new_analysis_results ^ elem(ModuleName) ->
+    ( map.search(!.Info ^ new_analysis_results, ModuleName, NewResults) ->
         ModuleStatus = lub_result_statuses(NewResults)
     ; 
         ModuleStatus = optimal,
@@ -1065,7 +1068,7 @@
     % Write the results for all the modules we know of.  For the module being
     % compiled, the analysis results may have changed. For other modules,
     % their overall statuses may have changed.
-    write_local_modules(!.Info, write_module_analysis_results,
+    write_local_modules(!.Info, write_module_status_and_analysis_results,
         !.Info ^ old_analysis_results, !IO),
 
     % Write the requests for the imported modules.
@@ -1083,16 +1086,7 @@
     % analysed.
     module_name_to_write_file_name(Compiler, ModuleName, ".analysis_date",
         TimestampFileName, !IO),
-    io.open_output(TimestampFileName, Result, !IO),
-    (
-        Result = ok(OutputStream),
-        io.write_string(OutputStream, "\n", !IO),
-        io.close_output(OutputStream, !IO)
-    ;
-        Result = error(IOError),
-        unexpected(this_file,
-            "write_analysis_files: " ++ io.error_message(IOError))
-    ).
+    touch_datestamp(TimestampFileName, !IO).
 
 :- type write_module_analysis_map(T) ==
     (pred(analysis_info, module_name, module_analysis_map(T), io, io)).
@@ -1123,19 +1117,23 @@
         ), !IO)
     ).
 
-:- pred write_module_analysis_results(analysis_info::in, module_name::in,
-    module_analysis_map(some_analysis_result)::in, io::di, io::uo) is det.
+:- pred write_module_status_and_analysis_results(analysis_info::in,
+    module_name::in, module_analysis_map(some_analysis_result)::in,
+    io::di, io::uo) is det.
 
-write_module_analysis_results(Info, ModuleName, ModuleResults, !IO) :-
+write_module_status_and_analysis_results(Info, ModuleName, ModuleResults,
+        !IO) :-
     ModuleStatus = Info ^ module_statuses ^ det_elem(ModuleName),
+    analysis.file.write_module_overall_status(Info, ModuleName,
+        ModuleStatus, !IO),
     analysis.file.write_module_analysis_results(Info, ModuleName,
-        ModuleStatus, ModuleResults, !IO).
+        ModuleResults, !IO).
 
 %-----------------------------------------------------------------------------%
 
-read_module_overall_status(Compiler, ModuleName, MaybeModuleStatus, !IO) :-
+read_module_overall_status(Compiler, ModuleName, ModuleStatus, !IO) :-
     analysis.file.read_module_overall_status(Compiler, ModuleName,
-        MaybeModuleStatus, !IO).
+        ModuleStatus, !IO).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/make.module_target.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.module_target.m,v
retrieving revision 1.61
diff -u -b -r1.61 make.module_target.m
--- compiler/make.module_target.m	27 Mar 2008 02:29:41 -0000	1.61
+++ compiler/make.module_target.m	29 May 2008 01:13:48 -0000
@@ -312,11 +312,15 @@
 force_reanalysis_of_suboptimal_module(ModuleName, ForceReanalysis, Info,
         !IO) :-
     ( Info ^ reanalysis_passes > 0 ->
-        analysis.read_module_overall_status(mmc, ModuleName,
-            MaybeAnalysisStatus, !IO),
-        ( MaybeAnalysisStatus = yes(suboptimal) ->
+        analysis.read_module_overall_status(mmc, ModuleName, AnalysisStatus,
+            !IO),
+        (
+            ( AnalysisStatus = suboptimal
+            ; AnalysisStatus = invalid
+            ),
             ForceReanalysis = yes
         ;
+            AnalysisStatus = optimal,
             ForceReanalysis = no
         )
     ;
Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.83
diff -u -b -r1.83 make.program_target.m
--- compiler/make.program_target.m	16 May 2008 08:10:51 -0000	1.83
+++ compiler/make.program_target.m	29 May 2008 01:13:48 -0000
@@ -853,9 +853,7 @@
 modules_needing_reanalysis(_, [], [], [], !IO).
 modules_needing_reanalysis(ReanalyseSuboptimal, [Module | Modules],
         InvalidModules, SuboptimalModules, !IO) :-
-    read_module_overall_status(mmc, Module, MaybeModuleStatus, !IO),
-    (
-        MaybeModuleStatus = yes(ModuleStatus),
+    read_module_overall_status(mmc, Module, ModuleStatus, !IO),
         (
             ModuleStatus = optimal,
             modules_needing_reanalysis(ReanalyseSuboptimal, Modules,
@@ -876,21 +874,6 @@
             modules_needing_reanalysis(ReanalyseSuboptimal, Modules,
                 InvalidModules0, SuboptimalModules, !IO),
             InvalidModules = [Module | InvalidModules0]
-        )
-    ;
-        MaybeModuleStatus = no,
-        % The analysis file does not exist.  For some reason it wasn't created
-        % in this or an earlier pass (and hence probably won't be created no
-        % matter how many times we repeat the analysis).
-        %
-        % XXX: Currently modules which are basically empty do not get
-        % `.analysis' files produced.  After that is fixed we can probably
-        % consider modules with missing `.analysis' files to be invalid.
-        %
-        % XXX: MaybeModuleStatus could be `no' for some other reason
-        %
-        modules_needing_reanalysis(ReanalyseSuboptimal, Modules,
-            InvalidModules, SuboptimalModules, !IO)
     ).
 
 :- pred reset_analysis_registry_dependency_status(module_name::in,
Index: compiler/make.util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.util.m,v
retrieving revision 1.54
diff -u -b -r1.54 make.util.m
--- compiler/make.util.m	27 Mar 2008 02:29:42 -0000	1.54
+++ compiler/make.util.m	29 May 2008 01:13:48 -0000
@@ -961,11 +961,9 @@
         get_target_timestamp_2(Search, Target, MaybeTimestamp, !Info, !IO)
     ).
 
-    % Special treatment for `.analysis' files.  If the `.analysis' file is
-    % valid then we look at the corresponding `.analysis_date' file to get the
-    % last time that the module was actually analysed (the file may have been
-    % rewritten or had it's status changed while analysing other modules).
-    % If the `.analysis' file is invalid then we treat it as out of date.
+    % Special treatment for `.analysis' files.  If the corresponding
+    % `.analysis_status' file says the `.analysis' file is invalid then we
+    % treat it as out of date.
     %
 :- pred get_target_timestamp_analysis_registry(bool::in, module_name::in,
     maybe_error(timestamp)::out, make_info::in, make_info::out,
@@ -973,36 +971,17 @@
 
 get_target_timestamp_analysis_registry(Search, ModuleName, MaybeTimestamp,
         !Info, !IO) :-
-    analysis.read_module_overall_status(mmc, ModuleName, MaybeStatus, !IO),
-    (
-        MaybeStatus = yes(Status),
+    analysis.read_module_overall_status(mmc, ModuleName, Status, !IO),
         (
             ( Status = optimal
             ; Status = suboptimal
             ),
-            get_timestamp_file_timestamp(
+        get_target_timestamp_2(Search,
                 target_file(ModuleName, module_target_analysis_registry),
-                MaybeTimestamp0, !Info, !IO),
-            (
-                MaybeTimestamp0 = ok(_),
-                MaybeTimestamp = MaybeTimestamp0
-            ;
-                MaybeTimestamp0 = error(_),
-                % If the `.analysis' file exists with status `optimal' or
-                % `suboptimal' but there is no `.analysis_date' file, then the
-                % `.analysis' file must just have been created while analysing
-                % a different module.
-                MaybeTimestamp = ok(oldest_timestamp)
-            )
+            MaybeTimestamp, !Info, !IO)
         ;
             Status = invalid,
             MaybeTimestamp = error("invalid module")
-        )
-    ;
-        MaybeStatus = no,
-        get_target_timestamp_2(Search,
-            target_file(ModuleName, module_target_analysis_registry),
-            MaybeTimestamp, !Info, !IO)
     ).
 
 :- pred get_target_timestamp_2(bool::in, target_file::in,



--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list