diff: modules.m: nested modules bug fixes

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Jul 10 08:01:49 AEST 1998


Estimated hours taken: 4

compiler/modules.m:
	Fix a couple of bugs in the computation of dependencies
	for the `--generate-dependencies' option:
	(1) it wasn't handling the case where the top-level file named
	    on the command line contained nested modules
	(2) it wasn't including the parent module's dependencies in the
	    dependencies for child modules.

Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.81
diff -u -r1.81 modules.m
--- modules.m	1998/07/01 04:09:39	1.81
+++ modules.m	1998/07/09 21:10:39
@@ -187,6 +187,21 @@
 % The `module_imports' structure holds information about
 % a module and the modules that it imports.
 
+% Note that we build this structure up as we go along.
+% When generating the dependencies (for `--generate-dependencies'),
+% the two fields that hold the direct imports do not include
+% the imports via ancestors when the module is first read in;
+% the ancestor imports are added later, once all the modules
+% have been read in.  Similarly the indirect imports field is
+% initially set to the empty list and filled in later.
+%
+% When compiling or when making interface files, the same
+% sort of thing applies: initially all the list(module_name) fields
+% except the public children field are set to empty lists,
+% and then we add ancestor modules and imported modules
+% to their respective lists as we process the interface files
+% for those imported or ancestor modules.
+
 :- type module_imports --->
 	module_imports(
 		file_name,	    % The source file
@@ -217,6 +232,9 @@
 :- pred module_imports_get_module_name(module_imports, module_name).
 :- mode module_imports_get_module_name(in, out) is det.
 
+:- pred module_imports_get_impl_deps(module_imports, list(module_name)).
+:- mode module_imports_get_impl_deps(in, out) is det.
+
 :- pred module_imports_get_items(module_imports, item_list).
 :- mode module_imports_get_items(in, out) is det.
 
@@ -229,6 +247,17 @@
 :- pred module_imports_set_error(module_imports, module_error, module_imports).
 :- mode module_imports_set_error(in, in, out) is det.
 
+% set the interface dependencies
+:- pred module_imports_set_int_deps(module_imports, list(module_name),
+				module_imports).
+:- mode module_imports_set_int_deps(in, in, out) is det.
+
+% set the implementation dependencies
+:- pred module_imports_set_impl_deps(module_imports, list(module_name),
+				module_imports).
+:- mode module_imports_set_impl_deps(in, in, out) is det.
+
+% set the indirect dependencies
 :- pred module_imports_set_indirect_deps(module_imports, list(module_name),
 				module_imports).
 :- mode module_imports_set_indirect_deps(in, in, out) is det.
@@ -1068,6 +1097,9 @@
 module_imports_get_module_name(Module, ModuleName) :-
 	Module = module_imports(_, ModuleName, _, _, _, _, _, _, _, _).
 
+module_imports_get_impl_deps(Module, ImplDeps) :-
+	Module = module_imports(_, _, _, _, ImplDeps, _, _, _, _, _).
+
 module_imports_get_items(Module, Items) :-
 	Module = module_imports(_, _, _, _, _, _, _, _, Items, _).
 
@@ -1082,6 +1114,14 @@
 	Module0 = module_imports(A, B, C, D, E, F, G, H, I, _),
 	Module = module_imports(A, B, C, D, E, F, G, H, I, Error).
 
+module_imports_set_int_deps(Module0, IntDeps, Module) :-
+	Module0 = module_imports(A, B, C, _, E, F, G, H, I, J),
+	Module = module_imports(A, B, C, IntDeps, E, F, G, H, I, J).
+
+module_imports_set_impl_deps(Module0, ImplDeps, Module) :-
+	Module0 = module_imports(A, B, C, D, _, F, G, H, I, J),
+	Module = module_imports(A, B, C, D, ImplDeps, F, G, H, I, J).
+
 module_imports_set_indirect_deps(Module0, IndirectDeps, Module) :-
 	Module0 = module_imports(A, B, C, D, E, _, G, H, I, J),
 	Module = module_imports(A, B, C, D, E, IndirectDeps, G, H, I, J).
@@ -1735,10 +1775,12 @@
 	read_mod_from_file(FileName, ".m", "Reading file", no,
 		Items, Error, ModuleName),
 	{ string__append(FileName, ".m", SourceFileName) },
-	{ init_dependencies(SourceFileName, Error, ModuleName - Items,
-		ModuleImports) },
+	{ split_into_submodules(ModuleName, Items, SubModuleList) },
+	{ list__map(init_dependencies(SourceFileName, Error), SubModuleList,
+		ModuleImportsList) },
 	{ map__init(DepsMap0) },
-	{ insert_into_deps_map(ModuleImports, DepsMap0, DepsMap1) },
+	{ list__foldl(insert_into_deps_map, ModuleImportsList,
+		DepsMap0, DepsMap1) },
 	generate_dependencies(ModuleName, DepsMap1).
 
 :- pred generate_dependencies(module_name, deps_map, io__state, io__state).
@@ -1788,6 +1830,10 @@
 		get_opt_deps(yes, TransOptDepsOrdering0, IntermodDirs,
 			".trans_opt", TransOptDepsOrdering),
 
+		% { relation__to_assoc_list(ImplDepsRel, ImplDepsAL) },
+		% print("ImplDepsAL:\n"),
+		% write_list(ImplDepsAL, "\n", print), nl,
+
 		%
 		% compute the indirect dependencies: they are equal to the
 		% composition of the implementation dependencies
@@ -1797,7 +1843,8 @@
 		{ relation__compose(ImplDepsRel, TransIntDepsRel,
 			IndirectDepsRel) },
 
-		generate_dependencies_write_d_files(DepsList, IndirectDepsRel,
+		generate_dependencies_write_d_files(DepsList,
+			IntDepsRel, ImplDepsRel, IndirectDepsRel,
 			TransOptDepsOrdering, DepsMap)
 	).
 
@@ -1846,27 +1893,27 @@
 %		TransOptOrder gives the ordering that is used to determine
 %		which other modules the .trans_opt files may depend on.
 :- pred generate_dependencies_write_d_files(list(deps)::in, 
-	relation(module_name)::in, list(module_name)::in, deps_map::in, 
-	io__state::di, io__state::uo) is det.
-generate_dependencies_write_d_files([], _, _TransOptOrder, _DepsMap) --> [].
+	deps_rel::in, deps_rel::in, deps_rel::in, list(module_name)::in,
+	deps_map::in, io__state::di, io__state::uo) is det.
+generate_dependencies_write_d_files([], _, _, _, _, _) --> [].
 generate_dependencies_write_d_files([Dep | Deps],
-		IndirectDepsRel0, TransOptOrder, DepsMap) --> 
+		IntDepsRel, ImplDepsRel, IndirectDepsRel,
+		TransOptOrder, DepsMap) --> 
 	{ Dep = deps(_, Module0) },
 
 	%
-	% Look up the indirect dependencies for this module
-	% from the indirect dependencies relation, and save
-	% them in the module_imports structure.
+	% Look up the interface/implementation/indirect dependencies
+	% for this module from the respective dependency relations,
+	% and save them in the module_imports structure.
 	%
 	{ module_imports_get_module_name(Module0, ModuleName) },
-	{ relation__add_element(IndirectDepsRel0, ModuleName, ModuleKey,
-		IndirectDepsRel) },
-	{ relation__lookup_from(IndirectDepsRel, ModuleKey,
-		IndirectDepsKeysSet) },
-	{ set__to_sorted_list(IndirectDepsKeysSet, IndirectDepsKeys) },
-	{ list__map(relation__lookup_key(IndirectDepsRel), IndirectDepsKeys,
-		IndirectDeps) },
-	{ module_imports_set_indirect_deps(Module0, IndirectDeps, Module) },
+	{ get_dependencies_from_relation(IntDepsRel, ModuleName, IntDeps) },
+	{ get_dependencies_from_relation(ImplDepsRel, ModuleName, ImplDeps) },
+	{ get_dependencies_from_relation(IndirectDepsRel, ModuleName,
+			IndirectDeps) },
+	{ module_imports_set_int_deps(Module0, IntDeps, Module1) },
+	{ module_imports_set_impl_deps(Module1, ImplDeps, Module2) },
+	{ module_imports_set_indirect_deps(Module2, IndirectDeps, Module) },
 
 	%
 	% Compute the trans-opt dependencies for this module.
@@ -1894,9 +1941,20 @@
 	;
 		[]
 	),
-	generate_dependencies_write_d_files(Deps, IndirectDepsRel,
+	generate_dependencies_write_d_files(Deps,
+		IntDepsRel, ImplDepsRel, IndirectDepsRel,
 		TransOptOrder, DepsMap).
 
+:- pred get_dependencies_from_relation(deps_rel, module_name,
+		list(module_name)).
+:- mode get_dependencies_from_relation(in, in, out) is det.
+
+get_dependencies_from_relation(DepsRel0, ModuleName, Deps) :-
+	relation__add_element(DepsRel0, ModuleName, ModuleKey, DepsRel),
+	relation__lookup_from(DepsRel, ModuleKey, DepsKeysSet),
+	set__to_sorted_list(DepsKeysSet, DepsKeys),
+	list__map(relation__lookup_key(DepsRel), DepsKeys, Deps).
+
 % This is the data structure we use to record the dependencies.
 % We keep a map from module name to information about the module.
 
@@ -1952,34 +2010,95 @@
 		IntRel0, IntRel, ImplRel0, ImplRel) :-
 	Deps = deps(_, ModuleImports),
 	ModuleImports = module_imports(_FileName, ModuleName,
-		ParentDeps, IntDeps, ImplDeps,
-		_IndirectDeps, PublicChildren, _FactDeps, _Items, ModuleError),
+		ParentDeps, _IntDeps, _ImplDeps,
+		_IndirectDeps, _PublicChildren, _FactDeps, _Items, ModuleError),
 	( ModuleError \= fatal ->
-		% add interface dependencies to the interface deps relation
+		%
+		% Add interface dependencies to the interface deps relation.
+		%
+		% Note that we need to do this both for the interface imports
+		% of this module and for the *implementation* imports of
+		% its ancestors.  This is because if this module is defined
+		% in the implementation section of its parent, then the
+		% interface of this module may depend on things
+		% imported only by its parent's implementation.
+		%
+		% If this module was actually defined in the interface
+		% section of one of its ancestors, then it should only
+		% depend on the interface imports of that ancestor,
+		% so the dependencies added here are in fact more
+		% conservative than they need to be in that case.
+		% However, that should not be a major problem.
+		% 
 		relation__add_element(IntRel0, ModuleName, IntModuleKey,
 			IntRel1),
-		AddIntDep = add_dep(IntModuleKey),
-		list__foldl(AddIntDep, ParentDeps, IntRel1, IntRel2),
-		list__foldl(AddIntDep, IntDeps, IntRel2, IntRel3),
-		list__foldl(AddIntDep, PublicChildren, IntRel3, IntRel4),
-
-		% add implementation dependencies to the impl. deps relation
-		% (the implementation dependencies are a superset of the
-		% interface dependencies)
+		add_int_deps(IntModuleKey, ModuleImports, IntRel1, IntRel2),
+		list__foldl(add_parent_impl_deps(DepsMap, IntModuleKey),
+				ParentDeps, IntRel2, IntRel3),
+
+		%
+		% Add implementation dependencies to the impl. deps relation.
+		% (The implementation dependencies are a superset of the
+		% interface dependencies.)
+		%
+		% Note that we need to do this both for the imports
+		% of this module and for the imports of its parents,
+		% because this module may depend on things imported
+		% only by its parents.
+		%
 		relation__add_element(ImplRel0, ModuleName, ImplModuleKey,
 			ImplRel1),
-		AddImplDep = add_dep(ImplModuleKey),
-		list__foldl(AddImplDep, ParentDeps, ImplRel1, ImplRel2),
-		list__foldl(AddImplDep, IntDeps, ImplRel2, ImplRel3),
-		list__foldl(AddImplDep, PublicChildren, ImplRel3, ImplRel4),
-		list__foldl(AddImplDep, ImplDeps, ImplRel4, ImplRel5)
+		add_impl_deps(ImplModuleKey, ModuleImports, ImplRel1, ImplRel2),
+		list__foldl(add_parent_impl_deps(DepsMap, ImplModuleKey),
+				ParentDeps, ImplRel2, ImplRel3)
 	;
-		IntRel4 = IntRel0,
-		ImplRel5 = ImplRel0
+		IntRel3 = IntRel0,
+		ImplRel3 = ImplRel0
 	),
 	deps_list_to_deps_rel(DepsList, DepsMap,
-		IntRel4, IntRel, ImplRel5, ImplRel).
+		IntRel3, IntRel, ImplRel3, ImplRel).
+
+% add interface dependencies to the interface deps relation
+%
+:- pred add_int_deps(relation_key, module_imports, deps_rel, deps_rel).
+:- mode add_int_deps(in, in, in, out) is det.
+
+add_int_deps(ModuleKey, ModuleImports, Rel0, Rel) :-
+	ModuleImports = module_imports(_FileName, _ModuleName,
+		ParentDeps, IntDeps, _ImplDeps, _IndirectDeps, PublicChildren,
+		_FactDeps, _Items, _ModuleError),
+	AddDep = add_dep(ModuleKey),
+	list__foldl(AddDep, ParentDeps, Rel0, Rel1),
+	list__foldl(AddDep, IntDeps, Rel1, Rel2),
+	list__foldl(AddDep, PublicChildren, Rel2, Rel).
 
+% add direct implementation dependencies for a module to the
+% impl. deps relation
+%
+:- pred add_impl_deps(relation_key, module_imports, deps_rel, deps_rel).
+:- mode add_impl_deps(in, in, in, out) is det.
+
+add_impl_deps(ModuleKey, ModuleImports, Rel0, Rel) :-
+	% the implementation dependencies are a superset of the
+	% interface dependencies, so first we add the interface deps
+	add_int_deps(ModuleKey, ModuleImports, Rel0, Rel1),
+	% then we add the impl deps
+	module_imports_get_impl_deps(ModuleImports, ImplDeps),
+	list__foldl(add_dep(ModuleKey), ImplDeps, Rel1, Rel).
+
+% add parent implementation dependencies for the given Parent module
+% to the impl. deps relation values for the given ModuleKey.
+%
+:- pred add_parent_impl_deps(deps_map, relation_key, module_name,
+			deps_rel, deps_rel).
+:- mode add_parent_impl_deps(in, in, in, in, out) is det.
+
+add_parent_impl_deps(DepsMap, ModuleKey, Parent, Rel0, Rel) :-
+	map__lookup(DepsMap, Parent, deps(_, ParentModuleImports)),
+	add_impl_deps(ModuleKey, ParentModuleImports, Rel0, Rel).
+
+% add a single dependency to a relation
+%
 :- pred add_dep(relation_key, T, relation(T), relation(T)).
 :- mode add_dep(in, in, in, out) is det.
 
@@ -1988,6 +2107,7 @@
 	relation__add(Relation1, ModuleRelKey, DepRelKey, Relation).
 
 %-----------------------------------------------------------------------------%
+
 	% Write out the `.dep' file, using the information collected in the
 	% deps_map data structure.
 :- pred generate_dependencies_write_dep_file(file_name::in, module_name::in,

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



More information about the developers mailing list