[m-rev.] for review: extra_info sections in .analysis files

Peter Wang wangp at students.cs.mu.OZ.AU
Fri Feb 17 15:46:33 AEDT 2006


Estimated hours taken: 5
Branches: main

analysis/analysis.file.m:
analysis/analysis.m:
	Add support for "extra info" sections in `.analysis' files.  These are
	intended to contain any data that may be necessary but wouldn't fit as
	answer patterns.

compiler/modules.m:
	Add `.imdg' and `.request' to the list of extensions treated specially
	by `make_file_name', so `--intermodule-analysis' works with
	`--use-grade-subdirs'.

Index: analysis/analysis.file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/analysis/analysis.file.m,v
retrieving revision 1.5
diff -u -r1.5 analysis.file.m
--- analysis/analysis.file.m	13 Feb 2006 03:47:39 -0000	1.5
+++ analysis/analysis.file.m	17 Feb 2006 03:35:53 -0000
@@ -15,35 +15,76 @@
 
 	% read_module_overall_status(Compiler, ModuleId, MaybeModuleStatus,
 	%   !IO)
+	%
 	% Attempt to read the overall status from a module `.analysis' 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_id::in,
 	maybe(analysis_status)::out, io::di, io::uo) is det
 	<= compiler(Compiler).
-
+	
+	% read_module_analysis_results(AnalysisInfo, ModuleId,
+	%   OverallStatus, AnalysisResults, ExtraInfo, !IO)
+	%
+	% Read the overall module status, analysis results and
+	% any extra info from a `.analysis' file.
+	%
 :- pred read_module_analysis_results(analysis_info::in, module_id::in,
 	analysis_status::out, module_analysis_map(analysis_result)::out,
-	io__state::di, io__state::uo) is det.
+	module_extra_info_map::out, io::di, io::uo) is det.
 
+	% write_module_analysis_results(AnalysisInfo, ModuleId,
+	%   OverallStatus, AnalysisResults, ExtraInfo, !IO)
+	%
+	% Write the overall module status, analysis results and
+	% extra info to a `.analysis' file.
+	%
 :- pred write_module_analysis_results(analysis_info::in,
 	module_id::in, analysis_status::in,
 	module_analysis_map(analysis_result)::in,
-	io__state::di, io__state::uo) is det.
+	module_extra_info_map::in, io::di, io::uo) is det.
 
+	% read_module_analysis_requests(AnalysisInfo, ModuleId,
+	%   ModuleRequests, !IO)
+	%
+	% Read outstanding analysis requests to a module from disk.
+	%
 :- pred read_module_analysis_requests(analysis_info::in,
 	module_id::in, module_analysis_map(analysis_request)::out,
 	io__state::di, io__state::uo) is det.
 
+	% write_module_analysis_requests(AnalysisInfo, ModuleId,
+	%   ModuleRequests, !IO)
+	%
+	% Write outstanding analysis requests for a module to disk.
+	%
 :- pred write_module_analysis_requests(analysis_info::in,
 	module_id::in, module_analysis_map(analysis_request)::in,
 	io__state::di, io__state::uo) is det.
 
+	% read_module_imdg(AnalysisInfo, ModuleId, ModuleEntries, !IO)
+	%
+	% Read the intermodule dependencies graph entries for a module
+	% from disk.
+	%
 :- pred read_module_imdg(analysis_info::in, module_id::in,
 	module_analysis_map(imdg_arc)::out, io::di, io::uo) is det.
 
+	% write_module_imdg(AnalysisInfo, ModuleId, ModuleEntries, !IO)
+	%
+	% Write the intermodule dependencies graph entries for a module
+	% to disk.
+	%
 :- pred write_module_imdg(analysis_info::in, module_id::in,
 	module_analysis_map(imdg_arc)::in, io::di, io::uo) is det.
 
+	% empty_request_file(AnalysisInfo, ModuleId, !IO)
+	%
+	% Delete the file containing outstanding analysis requests for a
+	% module.  This means all the analysis requests should have been
+	% satisfied already.
+	%
 :- pred empty_request_file(analysis_info::in, module_id::in,
 	io__state::di, io__state::uo) is det.
 
@@ -55,6 +96,7 @@
 %
 % version_number.
 % module_status.
+% extra_info(key, extra_info).
 % analysis_name(analysis_version, func_id, call_pattern, answer_pattern,
 %   result_status).
 
@@ -91,7 +133,21 @@
 	MaybeAnalysisFileName, !IO),
     (
 	MaybeAnalysisFileName = ok(AnalysisFileName),
-	read_module_overall_status_2(AnalysisFileName, MaybeModuleStatus, !IO)
+	read_module_overall_status_2(AnalysisFileName, MaybeModuleStatus0, !IO),
+	( MaybeModuleStatus0 = yes(optimal) ->
+	    module_id_to_read_file_name(Compiler, ModuleId, request_suffix,
+		MaybeRequestFileName, !IO),
+	    (
+		% There are outstanding requests for this module.
+		MaybeRequestFileName = ok(_),
+		MaybeModuleStatus = yes(suboptimal)
+	    ;
+		MaybeRequestFileName = error(_),
+		MaybeModuleStatus = MaybeModuleStatus0
+	    )
+	;
+	    MaybeModuleStatus = MaybeModuleStatus0
+	)
     ;
 	MaybeAnalysisFileName = error(_),
 	MaybeModuleStatus = no
@@ -131,16 +187,86 @@
 	MaybeModuleStatus = no
     ).
 
+%-----------------------------------------------------------------------------%
+
 read_module_analysis_results(Info, ModuleId, ModuleStatus, 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.
-	Compiler = Info ^ compiler,
-	read_analysis_file(Compiler, ModuleId, analysis_registry_suffix,
-		read_module_status, optimal, ModuleStatus,
-		parse_result_entry(Compiler),
-		map__init, ModuleResults, !IO).
+	ExtraInfo, !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.
+    Compiler = Info ^ compiler,
+    module_id_to_read_file_name(Compiler, ModuleId, analysis_registry_suffix,
+	MaybeAnalysisFileName, !IO),
+    (
+	MaybeAnalysisFileName = ok(AnalysisFileName),
+	read_module_analysis_results_2(Compiler, AnalysisFileName,
+	    ModuleStatus, ModuleResults, ExtraInfo, !IO)
+    ;
+	MaybeAnalysisFileName = error(_),
+	ModuleStatus = optimal,
+	ModuleResults = map.init,
+	ExtraInfo = map.init
+    ).
+
+:- pred read_module_analysis_results_2(Compiler::in, string::in,
+    analysis_status::out, module_analysis_map(analysis_result)::out,
+    module_extra_info_map::out, io::di, io::uo) is det <= compiler(Compiler).
+
+read_module_analysis_results_2(Compiler, AnalysisFileName,
+	ModuleStatus, ModuleResults, ExtraInfo, !IO) :-
+    ModuleResults0 = map.init,
+    io.open_input(AnalysisFileName, OpenResult, !IO),
+    (
+	OpenResult = ok(Stream),
+	debug_msg((pred(!.IO::di, !:IO::uo) is det :-
+	    io.print("Reading analysis registry file ", !IO),
+	    io.print(AnalysisFileName, !IO),
+	    io.nl(!IO)
+	), !IO),
+	io.set_input_stream(Stream, OldStream, !IO),
+
+	check_analysis_file_version_number(!IO),
+	read_module_status(ModuleStatus, !IO),
+	read_module_extra_infos(map.init, ExtraInfo,
+	    MaybeFirstResultEntry, !IO),
+	(
+	    MaybeFirstResultEntry = yes(FirstResultEntry),
+	    ParseEntry = parse_result_entry(Compiler),
+	    promise_only_solution_io(
+		(pred(Results3::out, !.IO::di, !:IO::uo) is cc_multi :-
+		    try_io((pred(Results2::out, !.IO::di, !:IO::uo) is det :-
+			ParseEntry(FirstResultEntry, ModuleResults0, Results1),
+			read_analysis_file_2(ParseEntry, Results1, Results2,
+			    !IO)
+		    ), Results3, !IO)
+		), Results, !IO),
+	    (
+		Results = succeeded(ModuleResults)
+	    ;
+		Results = failed,
+		ModuleResults = ModuleResults0
+	    ;
+		Results = exception(_),
+		% XXX Report error.
+		ModuleResults = ModuleResults0
+	    )
+	;
+	    MaybeFirstResultEntry = no,
+	    ModuleResults = map.init
+	),
+	io.set_input_stream(OldStream, _, !IO),
+	io.close_input(Stream, !IO)
+    ;
+	OpenResult = error(_),
+	debug_msg((pred(!.IO::di, !:IO::uo) is det :-
+	    io.print("Error reading analysis registry file: ", !IO),
+	    io.print(AnalysisFileName, !IO),
+	    io.nl(!IO)
+	), !IO),
+	ModuleStatus = optimal,
+	ModuleResults = ModuleResults0,
+	ExtraInfo = map.init
+    ).
 
 :- pred read_module_status(analysis_status::out, io::di, io::uo) is det.
 
@@ -164,6 +290,40 @@
 analysis_status_to_string(suboptimal, "suboptimal").
 analysis_status_to_string(optimal, "optimal").
 
+:- pred read_module_extra_infos(module_extra_info_map::in,
+    module_extra_info_map::out, maybe(term)::out, io::di, io::uo) is det.
+
+read_module_extra_infos(ExtraInfo0, ExtraInfo, MaybeFirstResultEntry, !IO) :-
+    parser.read_term(TermResult, !IO),
+    (
+	TermResult = eof,
+	ExtraInfo = ExtraInfo0,
+	MaybeFirstResultEntry = no
+    ;
+	TermResult = error(_, _),
+	throw(invalid_analysis_file)
+    ;
+	TermResult = term(_, Term),
+	(
+	    Term = term.functor(atom("extra_info"), Args, _)
+	->
+	    (
+		Args = [KeyTerm, ValueTerm],
+		KeyTerm = term.functor(string(Key), [], _),
+		ValueTerm = term.functor(string(Value), [], _)
+	    ->
+		map.det_insert(ExtraInfo0, Key, Value, ExtraInfo1),
+		read_module_extra_infos(ExtraInfo1, ExtraInfo,
+		    MaybeFirstResultEntry, !IO)
+	    ;
+		throw(invalid_analysis_file)
+	    )
+	;
+	    ExtraInfo = ExtraInfo0,
+	    MaybeFirstResultEntry = yes(Term)
+	)
+    ).
+
 :- pred parse_result_entry(Compiler::in)
 		`with_type` parse_entry(module_analysis_map(analysis_result))
 		`with_inst` parse_entry <= compiler(Compiler).
@@ -220,9 +380,10 @@
 	throw(invalid_analysis_file)
     ).
 
+%-----------------------------------------------------------------------------%
+
 read_module_analysis_requests(Info, ModuleId, ModuleRequests, !IO) :-
 	read_analysis_file(Info ^ compiler, ModuleId, request_suffix,
-		nop, unit, _NoHeader,
 		parse_request_entry(Info ^ compiler),
 		map__init, ModuleRequests, !IO).
 
@@ -276,9 +437,10 @@
 	throw(invalid_analysis_file)
     ).
 
+%-----------------------------------------------------------------------------%
+
 read_module_imdg(Info, ModuleId, ModuleEntries, !IO) :-
     read_analysis_file(Info ^ compiler, ModuleId, imdg_suffix,
-	nop, unit, _NoHeader,
 	parse_imdg_arc(Info ^ compiler),
 	map.init, ModuleEntries, !IO).
 
@@ -335,35 +497,30 @@
 :- inst parse_entry == (pred(in, in, out) is det).
 
 :- pred read_analysis_file(Compiler::in, module_id::in, string::in,
-		read_analysis_header(Header)::in(read_analysis_header),
-		Header::in, Header::out,
 		parse_entry(T)::in(parse_entry), T::in, T::out,
 		io__state::di, io__state::uo) is det <= compiler(Compiler).
 
 read_analysis_file(Compiler, ModuleId, Suffix,
-		ReadHeader, DefaultHeader, Header,
 		ParseEntry, ModuleResults0, ModuleResults, !IO) :-
 	module_id_to_read_file_name(Compiler, ModuleId,
 		Suffix, MaybeAnalysisFileName, !IO),
 	(
 		MaybeAnalysisFileName = ok(AnalysisFileName),
 		read_analysis_file(AnalysisFileName,
-			ReadHeader, DefaultHeader, Header,
 			ParseEntry, ModuleResults0, ModuleResults, !IO)
 	;
-		MaybeAnalysisFileName = error(_),
-		Header = DefaultHeader,
+		MaybeAnalysisFileName = error(Message),
+		debug_msg(io.print("Couldn't open " ++ Suffix ++
+			" for module " ++ ModuleId ++
+			": " ++ Message ++ "\n"), !IO),
 		ModuleResults = ModuleResults0
 	).
 
 :- pred read_analysis_file(string::in,
-		read_analysis_header(Header)::in(read_analysis_header),
-		Header::in, Header::out,
 		parse_entry(T)::in(parse_entry), T::in, T::out,
 		io__state::di, io__state::uo) is det.
 
 read_analysis_file(AnalysisFileName,
-		ReadHeader, DefaultHeader, Header,
 		ParseEntry, ModuleResults0, ModuleResults, !IO) :-
 	io__open_input(AnalysisFileName, OpenResult, !IO),
 	(
@@ -376,25 +533,21 @@
 		io__set_input_stream(Stream, OldStream, !IO),
 
 		promise_only_solution_io(
-		    (pred(HR::out, di, uo) is cc_multi -->
-			try_io((pred({Header1, Results1}::out, di, uo)
-				    is det -->
+		    (pred(R::out, di, uo) is cc_multi -->
+			try_io((pred(Results1::out, di, uo) is det -->
 			    check_analysis_file_version_number,
-			    ReadHeader(Header1),
 			    read_analysis_file_2(ParseEntry,
 			    		ModuleResults0, Results1)
-			), HR)
+			), R)
 		    ), Result, !IO),
 		(
-			Result = succeeded({Header, ModuleResults})
+			Result = succeeded(ModuleResults)
 		;
 			Result = failed,
-			Header = DefaultHeader,
 			ModuleResults = ModuleResults0
 		;
 			Result = exception(_),
 			% XXX Report error.
-			Header = DefaultHeader,
 			ModuleResults = ModuleResults0
 		),
 		io__set_input_stream(OldStream, _, !IO),
@@ -406,7 +559,6 @@
 			io.print(AnalysisFileName, !IO),
 			io.nl(!IO)
 		), !IO),
-		Header = DefaultHeader,
 		ModuleResults = ModuleResults0
 	).
 
@@ -441,18 +593,26 @@
 	).
 
 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
 
 write_module_analysis_results(Info, ModuleId, ModuleStatus, ModuleResults,
-		!IO) :-
-	debug_msg((pred(!.IO::di, !:IO::uo) is det :-
-		io.print("Writing module analysis results for ", !IO),
-		io.print(ModuleId, !IO),
-		io.nl(!IO)
-	), !IO),
-	WriteHeader = write_module_status(ModuleStatus),
-	write_analysis_file(Info ^ compiler,
-		ModuleId, analysis_registry_suffix,
-		WriteHeader, write_result_entry, ModuleResults, !IO).
+	ExtraInfo, !IO) :-
+    debug_msg((pred(!.IO::di, !:IO::uo) is det :-
+	io.print("Writing module analysis results for ", !IO),
+	io.print(ModuleId, !IO),
+	io.nl(!IO)
+    ), !IO),
+    WriteHeader = write_module_status_and_extra_info(ModuleStatus, ExtraInfo),
+    write_analysis_file(Info ^ compiler,
+	ModuleId, analysis_registry_suffix,
+	WriteHeader, write_result_entry, ModuleResults, !IO).
+
+:- pred write_module_status_and_extra_info(analysis_status::in,
+    module_extra_info_map::in, io::di, io::uo) is det.
+
+write_module_status_and_extra_info(Status, ExtraInfo, !IO) :-
+    write_module_status(Status, !IO),
+    map.foldl(write_extra_info, ExtraInfo, !IO).
 
 :- pred write_module_status(analysis_status::in, io::di, io::uo) is det.
 
@@ -461,6 +621,33 @@
     Term = functor(atom(String), [], context_init),
     analysis_status_to_string(Status, String).
 
+:- pred write_extra_info(extra_info_key::in, string::in,
+    io::di, io::uo) is det.
+
+write_extra_info(Key, Value, !IO) :-
+    term_io.write_term_nl(varset.init : varset, Term, !IO),
+    Term = functor(atom("extra_info"), [KeyTerm, ValueTerm], context_init),
+    KeyTerm = functor(string(Key), [], context_init),
+    ValueTerm = functor(string(Value), [], context_init).
+
+:- pred write_result_entry `with_type` write_entry(analysis_result)
+		`with_inst` write_entry.
+
+write_result_entry(AnalysisName, FuncId, Result, !IO) :-
+	Result = analysis_result(Call, Answer, Status),
+	VersionNumber = analysis_version_number(Call, Answer), 
+	analysis_status_to_string(Status, StatusString),
+	term_io__write_term_nl(varset__init `with_type` varset,
+		functor(atom(AnalysisName), [
+			functor(integer(VersionNumber), [], context_init),
+		    	functor(string(FuncId), [], context_init),
+			functor(string(to_string(Call)), [], context_init),
+			functor(string(to_string(Answer)), [], context_init),
+			functor(string(StatusString), [], context_init)
+		], context_init), !IO).
+
+%-----------------------------------------------------------------------------%
+
 write_module_analysis_requests(Info, ModuleId, ModuleRequests, !IO) :-
 	Compiler = Info ^ compiler,
 	module_id_to_write_file_name(Compiler, ModuleId, request_suffix,
@@ -511,22 +698,6 @@
 		true
 	).
 
-:- pred write_result_entry `with_type` write_entry(analysis_result)
-		`with_inst` write_entry.
-
-write_result_entry(AnalysisName, FuncId, Result, !IO) :-
-	Result = analysis_result(Call, Answer, Status),
-	VersionNumber = analysis_version_number(Call, Answer), 
-	analysis_status_to_string(Status, StatusString),
-	term_io__write_term_nl(varset__init `with_type` varset,
-		functor(atom(AnalysisName), [
-			functor(integer(VersionNumber), [], context_init),
-		    	functor(string(FuncId), [], context_init),
-			functor(string(to_string(Call)), [], context_init),
-			functor(string(to_string(Answer)), [], context_init),
-			functor(string(StatusString), [], context_init)
-		], context_init), !IO).
-
 :- pred write_request_entry(Compiler::in)
 		`with_type` write_entry(analysis_request)
 		`with_inst` write_entry <= compiler(Compiler).
@@ -553,6 +724,8 @@
 			functor(string(to_string(Call)), [], context_init)
 		], context_init), !IO).
 
+%-----------------------------------------------------------------------------%
+
 write_module_imdg(Info, ModuleId, ModuleEntries, !IO) :-
     write_analysis_file(Info ^ compiler, ModuleId, imdg_suffix,
 	nop, write_imdg_arc(Info ^ compiler), ModuleEntries, !IO).
@@ -642,6 +815,8 @@
 		    ), FuncResults)
 	    ), ModuleResults, !IO).
 
+%-----------------------------------------------------------------------------%
+
 empty_request_file(Info, ModuleId, !IO) :-
 	module_id_to_write_file_name(Info ^ compiler, ModuleId, request_suffix,
 		RequestFileName, !IO),
@@ -652,10 +827,8 @@
 	), !IO),
 	io__remove_file(RequestFileName, _, !IO).
 
+%-----------------------------------------------------------------------------%
+
 :- pred nop(io::di, io::uo) is det.
 
 nop(!IO).
-
-:- pred nop(unit::out, io::di, io::uo) is det.
-
-nop(unit, !IO).
Index: analysis/analysis.m
===================================================================
RCS file: /home/mercury1/repository/mercury/analysis/analysis.m,v
retrieving revision 1.5
diff -u -r1.5 analysis.m
--- analysis/analysis.m	13 Feb 2006 03:47:39 -0000	1.5
+++ analysis/analysis.m	17 Feb 2006 02:51:59 -0000
@@ -110,6 +110,10 @@
 :- typeclass answer_pattern(Answer)
 		<= (partial_order(Answer), to_string(Answer)) where [].
 
+:- type extra_info_key == string.
+
+:- typeclass extra_info(ExtraInfo) <= to_string(ExtraInfo) where [].
+
 :- typeclass partial_order(T) where [
 	pred more_precise_than(T::in, T::in) is semidet,
 	pred equivalent(T::in, T::in) is semidet
@@ -176,6 +180,11 @@
 	% N.B. Newly recorded results will NOT be found.  This
 	% is intended for looking up results from _other_ modules.
 	%
+	% If the returned best result has a call pattern that is different
+	% from the given call pattern, then it is the analysis writer's
+	% responsibility to request a more precise analysis from the
+	% called module, using `record_request'.
+	%
 :- pred lookup_best_result(module_id::in, func_id::in, Call::in,
 	maybe({Call, Answer, analysis_status})::out,
 	analysis_info::in, analysis_info::out, io::di, io::uo) is det
@@ -203,11 +212,24 @@
 	list(Call)::out, analysis_info::in, analysis_info::out,
 	io::di, io::uo) is det <= call_pattern(Call).
 
-	% Record a request for a local function.
+	% Record a request for a function in an imported module.
+	%
 :- pred record_request(analysis_name::in, module_id::in, func_id::in,
 	Call::in, analysis_info::in, analysis_info::out) is det
 	<= call_pattern(Call).
 
+	% Lookup extra information about a module, using the key given.
+	%
+:- pred lookup_module_extra_info(module_id::in, extra_info_key::in,
+	maybe(ExtraInfo)::out, analysis_info::in, analysis_info::out,
+	io::di, io::uo) is det <= extra_info(ExtraInfo).
+
+	% Record extra information about a module under the given key.
+	%
+:- pred record_module_extra_info(module_id::in, extra_info_key::in,
+	ExtraInfo::in, analysis_info::in, analysis_info::out) is det
+	<= extra_info(ExtraInfo).
+
 	% Should be called after all analysis is completed to write the
 	% requests and results for the current compilation to the
 	% analysis files.
@@ -267,6 +289,12 @@
 		old_analysis_results :: analysis_map(analysis_result),
 		new_analysis_results :: analysis_map(analysis_result),
 
+			% The extra info map stores any extra information
+			% needed by one or more analysis results.
+			%
+		old_extra_infos	    :: map(module_id, module_extra_info_map),
+		new_extra_infos	    :: map(module_id, module_extra_info_map),
+
 			% The Inter-module Dependency Graph records
 			% dependencies of an entire module's analysis results
 			% on another module's answer patterns. e.g. assume
@@ -317,6 +345,8 @@
 :- type module_analysis_map(T)	== map(analysis_name, func_analysis_map(T)).
 :- type func_analysis_map(T)	== map(func_id, list(T)).
 
+:- type module_extra_info_map	== map(extra_info_key, string).
+
 %-----------------------------------------------------------------------------%
 %
 % The "any" call pattern
@@ -336,7 +366,7 @@
 
 init_analysis_info(Compiler) =
     'new analysis_info'(Compiler, map__init, map__init, map__init, map__init,
-	map__init, map__init).
+	map__init, map__init, map__init, map__init).
 
 %-----------------------------------------------------------------------------%
 
@@ -519,7 +549,8 @@
     ),
     ( CallPatterns0 = ModuleRequests ^ elem(AnalysisName) ^ elem(FuncId) ->
         CallPatterns = list__filter_map(
-            (func(Call0) = Call is semidet :- univ(Call) = univ(Call0)),
+            (func(analysis_request(Call0)) = Call is semidet :-
+		univ(Call) = univ(Call0)),
             CallPatterns0)
     ;
         CallPatterns = []
@@ -588,6 +619,29 @@
     ).
 
 %-----------------------------------------------------------------------------%
+
+lookup_module_extra_info(ModuleId, Key, MaybeExtraInfo, !Info, !IO) :-
+    ensure_old_module_analysis_results_loaded(ModuleId, !Info, !IO),
+    ModuleExtraInfos = !.Info ^ old_extra_infos ^ det_elem(ModuleId),
+    (
+	String = ModuleExtraInfos ^ elem(Key),
+	ExtraInfo = from_string(String)
+    ->
+	MaybeExtraInfo = yes(ExtraInfo)
+    ;
+	MaybeExtraInfo = no
+    ).
+
+record_module_extra_info(ModuleId, Key, ExtraInfo, !Info) :-
+    ( ModuleMap0 = !.Info ^ new_extra_infos ^ elem(ModuleId) ->
+	ModuleMap1 = ModuleMap0
+    ;
+	ModuleMap1 = map.init
+    ),
+    ModuleMap = map.set(ModuleMap1, Key, to_string(ExtraInfo)),
+    !:Info = !.Info ^ new_extra_infos ^ elem(ModuleId) := ModuleMap.
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
     % The algorithm is from Nick's thesis, pp. 108-9.
@@ -813,6 +867,30 @@
     ).
 
 %-----------------------------------------------------------------------------%
+
+:- pred update_extra_infos(analysis_info::in, analysis_info::out) is det.
+
+update_extra_infos(Info0, Info) :-
+    map.foldl(update_extra_infos_2,
+	Info0 ^ new_extra_infos,
+	Info0 ^ old_extra_infos, ExtraInfos),
+    Info = (Info0
+	^ old_extra_infos := ExtraInfos)
+	^ new_extra_infos := map.init.
+
+:- pred update_extra_infos_2(module_id::in, module_extra_info_map::in,
+    map(module_id, module_extra_info_map)::in, 
+    map(module_id, module_extra_info_map)::out) is det.
+
+update_extra_infos_2(ModuleId, ExtraInfoB, ModuleMap0, ModuleMap) :-
+    ( ExtraInfoA = ModuleMap0 ^ elem(ModuleId) ->
+	map.overlay(ExtraInfoA, ExtraInfoB, ExtraInfo),
+	ModuleMap = ModuleMap0 ^ elem(ModuleId) := ExtraInfo
+    ;
+	ModuleMap = ModuleMap0 ^ elem(ModuleId) := ExtraInfoB
+    ).
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
     % For each module N imported by M:
@@ -892,10 +970,11 @@
 	map.lookup(!.Info ^ module_statuses, ModuleId, _StatusMustExist)
     else
 	read_module_analysis_results(!.Info, ModuleId,
-	    ModuleStatus, ModuleResults, !IO),
-	!:Info = (!.Info
+	    ModuleStatus, ModuleResults, ExtraInfos, !IO),
+	!:Info = ((!.Info
 		^ module_statuses ^ elem(ModuleId) := ModuleStatus)
-		^ old_analysis_results ^ elem(ModuleId) := ModuleResults
+		^ old_analysis_results ^ elem(ModuleId) := ModuleResults)
+		^ old_extra_infos ^ elem(ModuleId) := ExtraInfos
     ).
 
 :- pred ensure_old_imdg_loaded(module_id::in, analysis_info::in,
@@ -931,16 +1010,22 @@
     ),
 
     update_analysis_registry(!Info, !IO),
+    update_extra_infos(!Info),
 
     !:Info = !.Info ^ module_statuses ^ elem(ModuleId) := ModuleStatus,
 
     update_intermodule_dependencies(ModuleId, ImportedModuleIds,
 	!Info, !IO),
-    (if map.is_empty(!.Info ^ new_analysis_results) then
+    (if map.is_empty(!.Info ^ new_analysis_results),
+	map.is_empty(!.Info ^ new_extra_infos)
+    then
 	true
     else
-	io.print("Warning: new_analysis_results is not empty\n", !IO),
+	io.print("Warning: new_analysis_results or extra_infos is not empty\n",
+	    !IO),
 	io.print(!.Info ^ new_analysis_results, !IO),
+	io.nl(!IO),
+	io.print(!.Info ^ new_extra_infos, !IO),
 	io.nl(!IO)
     ),
 
@@ -1009,8 +1094,13 @@
 
 write_module_analysis_results(Info, ModuleId, ModuleResults, !IO) :-
     ModuleStatus = Info ^ module_statuses ^ det_elem(ModuleId),
-    write_module_analysis_results(Info, ModuleId,
-	ModuleStatus, ModuleResults, !IO).
+    ( ModuleExtraInfo0 = Info ^ old_extra_infos ^ elem(ModuleId) ->
+	ModuleExtraInfo = ModuleExtraInfo0
+    ;
+	ModuleExtraInfo = map.init
+    ),
+    analysis.file.write_module_analysis_results(Info, ModuleId,
+	ModuleStatus, ModuleResults, ModuleExtraInfo, !IO).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.373
diff -u -r1.373 modules.m
--- compiler/modules.m	13 Feb 2006 03:47:43 -0000	1.373
+++ compiler/modules.m	17 Feb 2006 04:36:46 -0000
@@ -1167,6 +1167,8 @@
             ( Ext = ".opt"
             ; Ext = ".trans_opt"
             ; Ext = ".analysis"
+            ; Ext = ".imdg"
+            ; Ext = ".request"
             )
         )
     ->
--------------------------------------------------------------------------
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