diff: Mmake support for nested modules

Fergus Henderson fjh at cs.mu.OZ.AU
Wed May 27 12:53:00 AEST 1998


Add Mmake support for nested sub-modules.

compiler/mercury_compile.m:
compiler/modules.m:
compiler/intermod.m:
	Pass down the source file name to various places.
	Store the source file name in the module_imports data structure.
	In various places, use this source file name instead of assuming
	that the source file name can be obtained from the module name.

compiler/modules.m:
	Change the generated .d and .dep files to use the source file names.
	Add hard-coded rules in the .d files if the source file name does not
	match the form expected by the pattern rules in scripts/Mmake.rules.
	XXX unfortunately the rules don't work right for parallel makes of
	    nested modules

scripts/Mmake.rules:
	Add a comment saying that any changes here might need to
	be duplicated in compiler/modules.m.

tests/hard_coded/Mmakefile:
tests/hard_coded/nested.m:
tests/hard_coded/nested2.m:
tests/hard_coded/nested.exp:
tests/hard_coded/nested2.exp:
	Add a couple of test cases for nested modules (XXX not enabled,
	due to the above-mentioned problem with parallel makes).

doc/reference_manual.texi:
	Update the "implementation bugs and limitations" section.

NEWS:
	Update the news about nested modules.

cvs diff -N compiler/intermod.m compiler/mercury_compile.m compiler/modules.m scripts/Mmake.rules tests/hard_coded/Mmakefile tests/hard_coded/nested.exp tests/hard_coded/nested.m tests/hard_coded/nested2.exp tests/hard_coded/nested2.m
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.51
diff -u -r1.51 intermod.m
--- intermod.m	1998/05/15 07:07:13	1.51
+++ intermod.m	1998/05/26 22:04:43
@@ -1283,7 +1283,7 @@
 		%
 		% Read in the .opt files for imported and ancestor modules.
 		%
-	{ Module0 = module_imports(ModuleName, Ancestors0, InterfaceDeps0,
+	{ Module0 = module_imports(_, ModuleName, Ancestors0, InterfaceDeps0,
 					ImplementationDeps0, _, _, _, _, _) },
 	{ list__condense([Ancestors0, InterfaceDeps0, ImplementationDeps0],
 		OptFiles) },
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.91
diff -u -r1.91 mercury_compile.m
--- mercury_compile.m	1998/05/26 20:31:19	1.91
+++ mercury_compile.m	1998/05/26 22:53:41
@@ -198,7 +198,7 @@
 		{ ModulesToLink = [] }
 	; { MakeInterface = yes } ->
 		{ split_into_submodules(ModuleName, Items0, SubModuleList) },
-		list__foldl(make_interface, SubModuleList),
+		list__foldl(make_interface(FileName), SubModuleList),
 		{ ModulesToLink = [] }
 	; { MakeShortInterface = yes } ->
 		{ split_into_submodules(ModuleName, Items0, SubModuleList) },
@@ -206,7 +206,7 @@
 		{ ModulesToLink = [] }
 	; { MakePrivateInterface = yes } ->
 		{ split_into_submodules(ModuleName, Items0, SubModuleList) },
-		list__foldl(make_private_interface, SubModuleList),
+		list__foldl(make_private_interface(FileName), SubModuleList),
 		{ ModulesToLink = [] }
 	; { ConvertToMercury = yes } ->
 		module_name_to_file_name(ModuleName, ".ugly", yes,
@@ -218,7 +218,7 @@
 		{ ModulesToLink = [] }
 	;
 		{ split_into_submodules(ModuleName, Items0, SubModuleList) },
-		list__foldl(compile, SubModuleList),
+		list__foldl(compile(FileName), SubModuleList),
 		list__map_foldl(module_to_link, SubModuleList, ModulesToLink)
 
 		% XXX it would be better to do something like
@@ -231,25 +231,26 @@
 		% i.e. compile nested modules to a single C file.
 	).
 
-:- pred make_interface(pair(module_name, item_list), io__state, io__state).
-:- mode make_interface(in, di, uo) is det.
+:- pred make_interface(file_name, pair(module_name, item_list),
+			io__state, io__state).
+:- mode make_interface(in, in, di, uo) is det.
 
-make_interface(Module - Items) -->
-	make_interface(Module, Items).
+make_interface(SourceFileName, ModuleName - Items) -->
+	make_interface(SourceFileName, ModuleName, Items).
 
 :- pred make_short_interface(pair(module_name, item_list),
 				io__state, io__state).
 :- mode make_short_interface(in, di, uo) is det.
 
-make_short_interface(Module - Items) -->
-	make_short_interface(Module, Items).
+make_short_interface(ModuleName - Items) -->
+	make_short_interface(ModuleName, Items).
 
-:- pred make_private_interface(pair(module_name, item_list),
+:- pred make_private_interface(file_name, pair(module_name, item_list),
 				io__state, io__state).
-:- mode make_private_interface(in, di, uo) is det.
+:- mode make_private_interface(in, in, di, uo) is det.
 
-make_private_interface(Module - Items) -->
-	make_private_interface(Module, Items).
+make_private_interface(SourceFileName, ModuleName - Items) -->
+	make_private_interface(SourceFileName, ModuleName, Items).
 
 :- pred module_to_link(pair(module_name, item_list), string,
 			io__state, io__state).
@@ -273,11 +274,13 @@
 	% The initial arrangement has the stage numbers increasing by three
 	% so that new stages can be slotted in without too much trouble.
 
-:- pred compile(pair(module_name, item_list), io__state, io__state).
-:- mode compile(in, di, uo) is det.
+:- pred compile(file_name, pair(module_name, item_list),
+		io__state, io__state).
+:- mode compile(in, in, di, uo) is det.
 
-compile(ModuleName - Items0) -->
-	grab_imported_modules(ModuleName, Items0, Module, Error2),
+compile(SourceFileName, ModuleName - Items0) -->
+	grab_imported_modules(SourceFileName, ModuleName, Items0,
+		Module, Error2),
 	( { Error2 \= fatal } ->
 		mercury_compile(Module)
 	;
@@ -487,7 +490,7 @@
 			% not creating the trans opt file, then import the
 			% trans_opt files for all the modules that are
 			% imported (or used), and for all ancestor modules.
-			{ Imports0 = module_imports(_Module, Ancestors,
+			{ Imports0 = module_imports(_File, _Module, Ancestors,
 				InterfaceImports, ImplementationImports,
 				_IndirectImports, _PublicChildren, _FactDeps,
 				_Items, _Error) },
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.73
diff -u -r1.73 modules.m
--- modules.m	1998/05/26 20:49:24	1.73
+++ modules.m	1998/05/27 01:58:43
@@ -125,23 +125,26 @@
 
 %-----------------------------------------------------------------------------%
 
-	% make_private_interface(ModuleName, Items):
-	%	Given a module name and the list of items in that module,
+	% make_private_interface(SourceFileName, ModuleName, Items):
+	%	Given a source file name and module name,
+	%	and the list of items in that module,
 	%	output the private (`.int0') interface file for the module.
 	%	(The private interface contains all the declarations in
 	%	the module, including those in the `implementation'
 	%	section; it is used when compiling sub-modules.)
 	%
-:- pred make_private_interface(module_name, item_list, io__state, io__state).
-:- mode make_private_interface(in, in, di, uo) is det.
+:- pred make_private_interface(file_name, module_name, item_list,
+				io__state, io__state).
+:- mode make_private_interface(in, in, in, di, uo) is det.
 
-	% make_interface(ModuleName, Items):
-	%	Given a module name and the list of items in that module,
+	% make_interface(SourceFileName, ModuleName, Items):
+	%	Given a source file name and module name,
+	%	and the list of items in that module,
 	%	output the long (`.int') and short (`.int2') interface files
 	%	for the module.
 	%
-:- pred make_interface(module_name, item_list, io__state, io__state).
-:- mode make_interface(in, in, di, uo) is det.
+:- pred make_interface(file_name, module_name, item_list, io__state, io__state).
+:- mode make_interface(in, in, in, di, uo) is det.
 
 	% 	Output the unqualified short interface file to <module>.int3.
 	%
@@ -155,7 +158,9 @@
 
 :- type module_imports --->
 	module_imports(
-		module_name,	    % The primary module name
+		file_name,	    % The source file
+		module_name,	    % The module (or sub-module) that we
+				    % are compiling.
 		list(module_name),  % The list of ancestor modules it inherits
 		list(module_name),  % The list of modules it directly imports
 				    % in the interface
@@ -175,6 +180,9 @@
 
 % Some access predicates for the module_imports structure
 
+:- pred module_imports_get_source_file_name(module_imports, file_name).
+:- mode module_imports_get_source_file_name(in, out) is det.
+
 :- pred module_imports_get_module_name(module_imports, module_name).
 :- mode module_imports_get_module_name(in, out) is det.
 
@@ -219,19 +227,22 @@
 
 %-----------------------------------------------------------------------------%
 
-	% grab_imported_modules(ModuleName, Items, Module, Error)
-	%	Given a module name and the list of items in that module,
+	% grab_imported_modules(SourceFileName, ModuleName,
+	%		Items, Module, Error)
+	%	Given a source file name and module name,
+	%	and the list of items in that module,
 	%	read in the private interface files for all the parent modules,
 	%	the long interface files for all the imported modules,
 	%	and the short interface files for all the indirectly imported
 	%	modules, and return a `module_imports' structure containing the
 	%	relevant information.
 	%
-:- pred grab_imported_modules(module_name, item_list, module_imports,
+:- pred grab_imported_modules(file_name, module_name, item_list, module_imports,
 			module_error, io__state, io__state).
-:- mode grab_imported_modules(in, in, out, out, di, uo) is det.
+:- mode grab_imported_modules(in, in, in, out, out, di, uo) is det.
 
-	% grab_unqual_imported_modules(ModuleName, Items, Module, Error):
+	% grab_unqual_imported_modules(SourceFileName, ModuleName,
+	%		Items, Module, Error):
 	%	Similar to grab_imported_modules, but only reads in
 	%	the unqualified short interfaces (.int3s),
 	%	and the .int0 files for parent modules,
@@ -240,9 +251,9 @@
 	%	Does not set the `PublicChildren' or `FactDeps'
 	%	fields of the module_imports structure.
 
-:- pred grab_unqual_imported_modules(module_name, item_list, module_imports,
-			module_error, io__state, io__state).
-:- mode grab_unqual_imported_modules(in, in, out, out, di, uo) is det.
+:- pred grab_unqual_imported_modules(file_name, module_name, item_list,
+			module_imports, module_error, io__state, io__state).
+:- mode grab_unqual_imported_modules(in, in, in, out, out, di, uo) is det.
 
 	% process_module_long_interfaces(Imports, Ext, IndirectImports0,
 	%			IndirectImports, Module0, Module):
@@ -558,8 +569,9 @@
 	% Read in the .int3 files that the current module depends on,
 	% and use these to qualify all the declarations
 	% as much as possible. Then write out the .int0 file.
-make_private_interface(ModuleName, Items0) -->
-	grab_unqual_imported_modules(ModuleName, Items0, Module, Error),
+make_private_interface(SourceFileName, ModuleName, Items0) -->
+	grab_unqual_imported_modules(SourceFileName, ModuleName, Items0,
+		Module, Error),
 		%
 		% Check whether we succeeded
 		%
@@ -593,13 +605,13 @@
 	% Read in the .int3 files that the current module depends on,
 	% and use these to qualify all items in the interface as much as
 	% possible. Then write out the .int and .int2 files.
-make_interface(ModuleName, Items0) -->
+make_interface(SourceFileName, ModuleName, Items0) -->
 	{ get_interface(Items0, no, InterfaceItems0) },
 		% 
 		% Get the .int3 files for imported modules
 		%
-	grab_unqual_imported_modules(ModuleName, InterfaceItems0,
-		Module0, Error),
+	grab_unqual_imported_modules(SourceFileName, ModuleName,
+		InterfaceItems0, Module0, Error),
 
 		%
 		% Check whether we succeeded
@@ -888,7 +900,7 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-grab_imported_modules(ModuleName, Items0, Module, Error) -->
+grab_imported_modules(SourceFileName, ModuleName, Items0, Module, Error) -->
 		%
 		% Find out which modules this one depends on
 		%
@@ -905,8 +917,8 @@
 	{ get_fact_table_dependencies(Items0, FactDeps) },
 	{ get_interface(Items0, no, InterfaceItems) },
 	{ get_children(InterfaceItems, PublicChildren) },
-	{ init_module_imports(ModuleName, Items0, PublicChildren, FactDeps,
-		Module0) },
+	{ init_module_imports(SourceFileName, ModuleName, Items0,
+		PublicChildren, FactDeps, Module0) },
 
 		% If this module has any seperately-compiled sub-modules,
 		% then we need to make everything in this module exported.
@@ -958,7 +970,8 @@
 %	like grab_imported_modules, but gets the `.int3' files
 %	instead of the `.int' and `.int2' files.
 
-grab_unqual_imported_modules(ModuleName, Items0, Module, Error) -->
+grab_unqual_imported_modules(SourceFileName, ModuleName, Items0,
+		Module, Error) -->
 		%
 		% Find out which modules this one depends on
 		%
@@ -969,7 +982,8 @@
 		% Construct the initial module import structure,
 		% and append a `:- imported' decl to the items.
 		%
-	{ init_module_imports(ModuleName, Items0, [], [], Module0) },
+	{ init_module_imports(SourceFileName, ModuleName, Items0, [], [],
+		Module0) },
 	{ append_pseudo_decl(Module0, imported, Module1) },
 
 		% Add `builtin' and `private_builtin' to the imported modules.
@@ -1002,44 +1016,48 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred init_module_imports(module_name, item_list, list(module_name),
-				list(string), module_imports).
-:- mode init_module_imports(in, in, in, in, out) is det.
-
-init_module_imports(ModuleName, Items, PublicChildren, FactDeps, Module) :-
-	Module = module_imports(ModuleName, [], [], [], [],
+:- pred init_module_imports(file_name, module_name, item_list,
+			list(module_name), list(string), module_imports).
+:- mode init_module_imports(in, in, in, in, in, out) is det.
+
+init_module_imports(SourceFileName, ModuleName, Items, PublicChildren,
+			FactDeps, Module) :-
+	Module = module_imports(SourceFileName, ModuleName, [], [], [], [],
 			PublicChildren, FactDeps, Items, no).
 
+module_imports_get_source_file_name(Module, SourceFileName) :-
+	Module = module_imports(SourceFileName, _, _, _, _, _, _, _, _, _).
+
 module_imports_get_module_name(Module, ModuleName) :-
-	Module = module_imports(ModuleName, _, _, _, _, _, _, _, _).
+	Module = module_imports(_, ModuleName, _, _, _, _, _, _, _, _).
 
 module_imports_get_items(Module, Items) :-
-	Module = module_imports(_, _, _, _, _, _, _, Items, _).
+	Module = module_imports(_, _, _, _, _, _, _, _, Items, _).
 
 module_imports_set_items(Module0, Items, Module) :-
-	Module0 = module_imports(A, B, C, D, E, F, G, _, I),
-	Module = module_imports(A, B, C, D, E, F, G, Items, I).
+	Module0 = module_imports(A, B, C, D, E, F, G, H, _, J),
+	Module = module_imports(A, B, C, D, E, F, G, H, Items, J).
 
 module_imports_get_error(Module, Error) :-
-	Module = module_imports(_, _, _, _, _, _, _, _, Error).
+	Module = module_imports(_, _, _, _, _, _, _, _, _, Error).
 
 module_imports_set_error(Module0, Error, Module) :-
-	Module0 = module_imports(A, B, C, D, E, F, G, H, _),
-	Module = module_imports(A, B, C, D, E, F, G, H, Error).
+	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_indirect_deps(Module0, IndirectDeps, Module) :-
-	Module0 = module_imports(A, B, C, D, _, F, G, H, I),
-	Module = module_imports(A, B, C, D, IndirectDeps, F, G, H, I).
+	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).
 
 append_pseudo_decl(Module0, PseudoDecl, Module) :-
-	Module0 = module_imports(ModuleName, Ancestors, IntDeps, ImplDeps,
-				IndirectDeps, PublicChildren, FactDeps,
-				Items0, Error),
+	Module0 = module_imports(FileName, ModuleName, Ancestors, IntDeps,
+			ImplDeps, IndirectDeps, PublicChildren, FactDeps,
+			Items0, Error),
 	make_pseudo_decl(PseudoDecl, Item),
 	list__append(Items0, [Item], Items),
-	Module = module_imports(ModuleName, Ancestors, IntDeps, ImplDeps,
-				IndirectDeps, PublicChildren, FactDeps,
-				Items, Error).
+	Module = module_imports(FileName, ModuleName, Ancestors, IntDeps,
+			ImplDeps, IndirectDeps, PublicChildren, FactDeps,
+			Items, Error).
 
 make_pseudo_decl(PseudoDecl, Item) :-
 	term__context_init(Context),
@@ -1183,8 +1201,9 @@
 %-----------------------------------------------------------------------------%
 
 write_dependency_file(Module, MaybeTransOptDeps) -->
-	{ Module = module_imports(ModuleName, ParentDeps, IntDeps, ImplDeps,
-			IndirectDeps, _InclDeps, FactDeps0, _Items, _Error) },
+	{ Module = module_imports(SourceFileName, ModuleName, ParentDeps,
+			IntDeps, ImplDeps, IndirectDeps, _InclDeps, FactDeps0,
+			_Items, _Error) },
 	globals__io_lookup_bool_option(verbose, Verbose),
 	{ module_name_to_make_var_name(ModuleName, MakeVarName) },
 	module_name_to_file_name(ModuleName, ".d", yes, DependencyFileName),
@@ -1264,17 +1283,26 @@
 			[]
 		),
 
+		{
+			string__remove_suffix(SourceFileName, ".m",
+				SourceFileBase)
+		->
+			string__append(SourceFileBase, ".err", ErrFileName)
+		;
+			error("modules.m: source file doesn't end in `.m'")
+		},
 		module_name_to_file_name(ModuleName, ".optdate", no,
 					OptDateFileName),
 		module_name_to_file_name(ModuleName, ".c", no, CFileName),
-		module_name_to_file_name(ModuleName, ".err", no, ErrFileName),
 		module_name_to_file_name(ModuleName, ".o", no, ObjFileName),
-		module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
+		module_name_to_file_name(ModuleName, ".pic_o", no,
+							PicObjFileName),
 		io__write_strings(DepStream, ["\n\n",
 			OptDateFileName, " ",
 			TransOptDateFileName, " ",
 			CFileName, " ",
 			ErrFileName, " ",
+			PicObjFileName, " ",
 			ObjFileName, " : ",
 			SourceFileName
 		] ),
@@ -1303,6 +1331,7 @@
 				CFileName, " ",
 				TransOptDateFileName, " ",
 				ErrFileName, " ", 
+				PicObjFileName, " ",
 				ObjFileName, " :"
 			]),
 			% The .c file only depends on the .opt files from 
@@ -1327,6 +1356,7 @@
 					"\n\n", 
 					CFileName, " ",
 					ErrFileName, " ", 
+					PicObjFileName, " ", 
 					ObjFileName, " :"
 				]),
 				write_dependencies_list(TransOptDeps,
@@ -1353,7 +1383,7 @@
 		write_dependencies_list(ParentDeps, ".int0", DepStream),
 		write_dependencies_list(LongDeps, ".int3", DepStream),
 		write_dependencies_list(ShortDeps, ".int3", DepStream),
-
+			
 		module_name_to_file_name(ModuleName, ".dir", no, DirFileName),
 		module_name_to_split_c_file_name(ModuleName, 0, ".o",
 			SplitCObj0FileName),
@@ -1366,6 +1396,66 @@
 				SourceFileName, "\n"
 		]),
 
+		module_name_to_file_name(ModuleName, ".m", no,
+			ExpectedSourceFileName),
+		( { SourceFileName \= ExpectedSourceFileName } ->
+			%
+			% The pattern rules in Mmake.rules won't work,
+			% since the source file name doesn't match the
+			% expected source file name for this module name.
+			% This can occur due to just the use of different 
+			% source file names, or it can be due to the use
+			% of nested modules.  So we need to output
+			% hard-coded rules in this case.
+			%
+			% The rules output below won't work in the case
+			% of nested modules with parallel makes,
+			% because it will end up invoking the same
+			% command twice (since it produces two output files)
+			% at the same time.
+			%
+			% Any changes here will require corresponding
+			% changes to scripts/Mmake.rules.  See that
+			% file for documentation on these rules.
+			%
+			module_name_to_file_name(ModuleName, ".date3", no,
+							Date3FileName),
+			io__write_strings(DepStream, [
+				"\n",
+				Date0FileName, " : ", SourceFileName, "\n",
+				"\t$(MCPI) $(MCPIFLAGS) $<\n",
+				DateFileName, " : ", SourceFileName, "\n",
+				"\t$(MCI) $(MCIFLAGS) $<\n",
+				Date3FileName, " : ", SourceFileName, "\n",
+				"\t$(MCSI) $(MCSIFLAGS) $<\n",
+				OptDateFileName, " : ", SourceFileName, "\n",
+				"\t$(MCOI) $(MCOIFLAGS) $<\n",
+				TransOptDateFileName, " : ", SourceFileName,
+					"\n",
+				"\t$(MCTOI) $(MCTOIFLAGS) $<\n",
+				CFileName, " : ", SourceFileName, "\n",
+				"\trm -f ", CFileName, "\n",
+				"\t$(MCG) $(GRADEFLAGS) $(MCGFLAGS) $< ",
+					"> ", ErrFileName, " 2>&1\n",
+				"ifneq ($(RM_C),:)\n",
+				ObjFileName, " : ", SourceFileName, "\n",
+				"\t$(MMAKE_MAKE_CMD) $(MFLAGS) GRADEFLAGS=",
+					"""$(GRADEFLAGS)"" ", CFileName, "\n",
+				"\t$(MGNUC) $(GRADEFLAGS) $(MGNUCFLAGS) -c ",
+					CFileName, " -o $@\n",
+				"\t$(RM_C) ", CFileName, "\n",
+				PicObjFileName, " : ", SourceFileName, "\n",
+				"\t$(MMAKE_MAKE_CMD) $(MFLAGS) GRADEFLAGS=",
+					"""$(GRADEFLAGS)"" ", CFileName, "\n",
+				"\t$(MGNUC) $(GRADEFLAGS) $(MGNUCFLAGS) ",
+					"$(CFLAGS_FOR_PIC) \\\n",
+				"\t\t-c ", CFileName, " -o $@\n",
+				"endif # RM_C != :\n"
+			])
+		;
+			[]
+		),
+
 		io__close_output(DepStream),
 		io__rename_file(TmpDependencyFileName, DependencyFileName,
 			Result3),
@@ -1537,22 +1627,25 @@
 
 %-----------------------------------------------------------------------------%
 
-generate_dependencies(Module) -->
+generate_dependencies(ModuleName) -->
 	% first, build up a map of the dependencies.
 	{ map__init(DepsMap0) },
-	generate_deps_map([Module], DepsMap0, DepsMap),
+	generate_deps_map([ModuleName], DepsMap0, DepsMap),
 	%
 	% check whether we could read the main `.m' file
 	%
-	{ map__lookup(DepsMap, Module, deps(_, ModuleImports)) },
+	{ map__lookup(DepsMap, ModuleName, deps(_, ModuleImports)) },
 	{ module_imports_get_error(ModuleImports, Error) },
 	( { Error = fatal } ->
-		{ prog_out__sym_name_to_string(Module, ModuleString) },
+		{ prog_out__sym_name_to_string(ModuleName, ModuleString) },
 		{ string__append_list(["fatal error reading module `",
 			ModuleString, "'."], Message) },
 		report_error(Message)
 	;
-		generate_dependencies_write_dep_file(Module, DepsMap),
+		{ module_imports_get_source_file_name(ModuleImports,
+			SourceFileName) },
+		generate_dependencies_write_dep_file(SourceFileName, ModuleName,
+			DepsMap),
 
 		%
 		% compute the interface deps relation and
@@ -1571,7 +1664,7 @@
 		% we have (or can make) trans-opt files.
 		%
 		{ relation__atsort(ImplDepsRel, ImplDepsOrdering0) },
-		maybe_output_module_order(Module, ImplDepsOrdering0),
+		maybe_output_module_order(ModuleName, ImplDepsOrdering0),
 		{ list__map(set__to_sorted_list, ImplDepsOrdering0, 
 			ImplDepsOrdering) },
 		{ list__condense(ImplDepsOrdering, TransOptDepsOrdering0) },
@@ -1715,7 +1808,7 @@
 	( { Done = no } ->
 		{ map__set(DepsMap1, Module, deps(yes, ModuleImports),
 			DepsMap2) },
-		{ ModuleImports = module_imports(_,
+		{ ModuleImports = module_imports(_, _,
 			ParentDeps, IntDeps, ImplDeps, _, InclDeps, _, _, _) },
 		{ list__condense(
 			[ParentDeps, IntDeps, ImplDeps, InclDeps, Modules],
@@ -1739,7 +1832,7 @@
 deps_list_to_deps_rel([Deps | DepsList], DepsMap,
 		IntRel0, IntRel, ImplRel0, ImplRel) :-
 	Deps = deps(_, ModuleImports),
-	ModuleImports = module_imports(ModuleName,
+	ModuleImports = module_imports(_FileName, ModuleName,
 		ParentDeps, IntDeps, ImplDeps,
 		_IndirectDeps, PublicChildren, _FactDeps, _Items, ModuleError),
 	( ModuleError \= fatal ->
@@ -1778,9 +1871,9 @@
 %-----------------------------------------------------------------------------%
 	% Write out the `.dep' file, using the information collected in the
 	% deps_map data structure.
-:- pred generate_dependencies_write_dep_file(module_name::in, deps_map::in, 
-	io__state::di, io__state::uo) is det.
-generate_dependencies_write_dep_file(ModuleName, DepsMap) -->
+:- pred generate_dependencies_write_dep_file(file_name::in, module_name::in,
+		deps_map::in, io__state::di, io__state::uo) is det.
+generate_dependencies_write_dep_file(SourceFileName, ModuleName, DepsMap) -->
 	globals__io_lookup_bool_option(verbose, Verbose),
 	module_name_to_file_name(ModuleName, ".dep", yes, DepFileName),
 	maybe_write_string(Verbose, "% Creating auto-dependency file `"),
@@ -1788,7 +1881,8 @@
 	maybe_write_string(Verbose, "'...\n"),
 	io__open_output(DepFileName, DepResult),
 	( { DepResult = ok(DepStream) } ->
-		generate_dep_file(ModuleName, DepsMap, DepStream),
+		generate_dep_file(SourceFileName, ModuleName, DepsMap,
+			DepStream),
 		io__close_output(DepStream),
 		maybe_write_string(Verbose, "% done.\n")
 	;
@@ -1798,16 +1892,21 @@
 	).
 
 
-:- pred generate_dep_file(module_name, deps_map, io__output_stream,
+:- pred generate_dep_file(file_name, module_name, deps_map, io__output_stream,
 			io__state, io__state).
-:- mode generate_dep_file(in, in, in, di, uo) is det.
+:- mode generate_dep_file(in, in, in, in, di, uo) is det.
 
-generate_dep_file(ModuleName, DepsMap, DepStream) -->
+generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream) -->
 	io__write_string(DepStream,
 		"# Automatically generated dependencies for module `"),
 	{ prog_out__sym_name_to_string(ModuleName, ModuleNameString) },
 	io__write_string(DepStream, ModuleNameString),
-	io__write_string(DepStream, "'.\n"),
+	io__write_string(DepStream, "'\n"),
+	io__write_string(DepStream,
+		"# generated from source file `"),
+	io__write_string(DepStream, SourceFileName),
+	io__write_string(DepStream, "'\n"),
+
 	{ library__version(Version) },
 	io__write_string(DepStream,
 		"# Generated by the Mercury compiler, version "),
@@ -1818,15 +1917,28 @@
 	{ select_ok_modules(Modules0, DepsMap, Modules) },
 
 	{ module_name_to_make_var_name(ModuleName, MakeVarName) },
+	{ list__map(get_source_file(DepsMap), Modules, SourceFiles0) },
+	{ list__sort_and_remove_dups(SourceFiles0, SourceFiles) },
+
 	io__write_string(DepStream, MakeVarName),
 	io__write_string(DepStream, ".ms ="),
-	write_dependencies_list(Modules, ".m", DepStream),
+	write_file_dependencies_list(SourceFiles, ".m", DepStream),
+	io__write_string(DepStream, "\n"),
+
+	io__write_string(DepStream, MakeVarName),
+	io__write_string(DepStream, ".errs ="),
+	write_file_dependencies_list(SourceFiles, ".err", DepStream),
+	io__write_string(DepStream, "\n"),
+
+	io__write_string(DepStream, MakeVarName),
+	io__write_string(DepStream, ".mods ="),
+	write_dependencies_list(Modules, "", DepStream),
 	io__write_string(DepStream, "\n\n"),
 
 	globals__io_lookup_bool_option(assume_gmake, Gmake),
 	( { Gmake = yes } ->
-		{ string__append(MakeVarName, ".ms", VarName) },
-		{ Basis = yes(VarName - ".m") }
+		{ string__append(MakeVarName, ".mods", ModsVarName) },
+		{ Basis = yes(ModsVarName - "") }
 	;
 		{ Basis = no }
 	),
@@ -1884,11 +1996,6 @@
 	io__write_string(DepStream, "\n"),
 
 	io__write_string(DepStream, MakeVarName),
-	io__write_string(DepStream, ".errs = "),
-	write_compact_dependencies_list(Modules, "", ".err", Basis, DepStream),
-	io__write_string(DepStream, "\n"),
-
-	io__write_string(DepStream, MakeVarName),
 	io__write_string(DepStream, ".dates = "),
 	write_compact_dependencies_list(Modules, "$(dates_subdir)", ".date",
 					Basis, DepStream),
@@ -2205,6 +2312,21 @@
 		"\t-rm -f $(", MakeVarName, ".qls)\n\n"
 	]).
 
+:- pred get_source_file(deps_map, module_name, file_name).
+:- mode get_source_file(in, in, out) is det.
+
+get_source_file(DepsMap, ModuleName, FileName) :-
+	map__lookup(DepsMap, ModuleName, Deps),
+	Deps = deps(_, ModuleImports),
+	module_imports_get_source_file_name(ModuleImports, SourceFileName),
+	(
+		string__remove_suffix(SourceFileName, ".m", SourceFileBase)
+	->
+		FileName = SourceFileBase
+	;
+		error("modules.m: source file name doesn't end in `.m'")
+	).
+
 :- pred append_to_init_list(io__output_stream, file_name, module_name,
 				io__state, io__state).
 :- mode append_to_init_list(in, in, in, di, uo) is det.
@@ -2233,7 +2355,7 @@
 get_extra_link_objects_2([Module | Modules], DepsMap, 
 		ExtraLinkObjs0, ExtraLinkObjs) :-
 	map__lookup(DepsMap, Module, deps(_, ModuleImports)),
-	ModuleImports = module_imports(_, _, _, _, _, _, FactDeps, _, _),
+	ModuleImports = module_imports(_, _, _, _, _, _, _, FactDeps, _, _),
 	list__append(FactDeps, ExtraLinkObjs0, ExtraLinkObjs1),
 	get_extra_link_objects_2(Modules, DepsMap, ExtraLinkObjs1, 
 		ExtraLinkObjs).
@@ -2338,19 +2460,27 @@
 		{ ModuleImports0 = ModuleImports },
 		{ DepsMap = DepsMap0 }
 	;
-		read_dependencies(Module, Search, ModuleImports),
-		{ map__det_insert(DepsMap0, Module, deps(no, ModuleImports),
-			DepsMap) },
-		{ Done = no }
-	).
+		read_dependencies(Module, Search, ModuleImportsList),
+		{ list__foldl(insert_into_deps_map, ModuleImportsList,
+			DepsMap0, DepsMap) },
+		{ map__lookup(DepsMap, Module, deps(Done, ModuleImports)) }
+	).
+
+:- pred insert_into_deps_map(module_imports, deps_map, deps_map).
+:- mode insert_into_deps_map(in, in, out) is det.
+insert_into_deps_map(ModuleImports, DepsMap0, DepsMap) :-
+	module_imports_get_module_name(ModuleImports, ModuleName),
+	map__det_insert(DepsMap0, ModuleName, deps(no, ModuleImports),
+		DepsMap).
 
-	% Read a module to determine its (direct) dependencies
+	% Read a module to determine the (direct) dependencies
+	% of that module and any nested sub-modules it contains.
 
-:- pred read_dependencies(module_name, bool, module_imports,
+:- pred read_dependencies(module_name, bool, list(module_imports),
 			io__state, io__state).
 :- mode read_dependencies(in, in, out, di, uo) is det.
 
-read_dependencies(ModuleName, Search, ModuleImports) -->
+read_dependencies(ModuleName, Search, ModuleImportsList) -->
 	read_mod_ignore_errors(ModuleName, ".m",
 		"Getting dependencies for module", Search, Items0, Error),
 	( { Items0 = [], Error = fatal } ->
@@ -2360,32 +2490,41 @@
 	;
 		{ Items = Items0 }
 	),
-
-	{ get_ancestors(ModuleName, ParentDeps) },
-
-	{ get_dependencies(Items, ImplImportDeps0, ImplUseDeps0) },
-	{ add_implicit_imports(ImplImportDeps0, ImplUseDeps0,
-		ImplImportDeps, ImplUseDeps) },
-	{ list__append(ImplImportDeps, ImplUseDeps, ImplementationDeps) },
-
-	{ get_interface(Items, no, InterfaceItems) },
-	{ get_dependencies(InterfaceItems, InterfaceImportDeps0,
-		InterfaceUseDeps0) },
-	{ add_implicit_imports(InterfaceImportDeps0, InterfaceUseDeps0,
-		InterfaceImportDeps, InterfaceUseDeps) },
-	{ list__append(InterfaceImportDeps, InterfaceUseDeps, 
-		InterfaceDeps) },
+	module_name_to_file_name(ModuleName, ".m", no, FileName),
+	{ split_into_submodules(ModuleName, Items, SubModuleList) },
+	{ list__map(read_dependencies_2(FileName, Error), SubModuleList,
+		ModuleImportsList) }.
+
+:- pred read_dependencies_2(file_name, module_error,
+		pair(module_name, item_list), module_imports).
+:- mode read_dependencies_2(in, in, in, out) is det.
+
+read_dependencies_2(FileName, Error, ModuleName - Items, ModuleImports) :-
+	get_ancestors(ModuleName, ParentDeps),
+
+	get_dependencies(Items, ImplImportDeps0, ImplUseDeps0),
+	add_implicit_imports(ImplImportDeps0, ImplUseDeps0,
+		ImplImportDeps, ImplUseDeps),
+	list__append(ImplImportDeps, ImplUseDeps, ImplementationDeps),
+
+	get_interface(Items, no, InterfaceItems),
+	get_dependencies(InterfaceItems, InterfaceImportDeps0,
+		InterfaceUseDeps0),
+	add_implicit_imports(InterfaceImportDeps0, InterfaceUseDeps0,
+		InterfaceImportDeps, InterfaceUseDeps),
+	list__append(InterfaceImportDeps, InterfaceUseDeps, 
+		InterfaceDeps),
 
 	% we don't fill in the indirect dependencies yet
-	{ IndirectDeps = [] },
+	IndirectDeps = [],
 
-	{ get_children(InterfaceItems, IncludeDeps) },
+	get_children(InterfaceItems, IncludeDeps),
 
-	{ get_fact_table_dependencies(Items, FactTableDeps) },
+	get_fact_table_dependencies(Items, FactTableDeps),
 
-	{ ModuleImports = module_imports(ModuleName, ParentDeps, InterfaceDeps,
-		ImplementationDeps, IndirectDeps, IncludeDeps, FactTableDeps,
-		[], Error) }.
+	ModuleImports = module_imports(FileName, ModuleName, ParentDeps,
+		InterfaceDeps, ImplementationDeps, IndirectDeps, IncludeDeps,
+		FactTableDeps, [], Error).
 
 %-----------------------------------------------------------------------------%
 
@@ -2456,7 +2595,7 @@
 process_module_private_interfaces([Ancestor | Ancestors],
 		DirectImports0, DirectImports, DirectUses0, DirectUses,
 		Module0, Module) -->
-	{ Module0 = module_imports(ModuleName, ModAncestors0,
+	{ Module0 = module_imports(FileName, ModuleName, ModAncestors0,
 				ModInterfaceDeps, ModImplementationDeps,
 				ModIndirectDeps, ModPublicChildren,
 				ModFactDeps, ModItems0, ModError0) },
@@ -2492,7 +2631,7 @@
 				DirectImports1) },
 		{ list__append(DirectUses0, AncDirectUses, DirectUses1) },
 		{ list__append(ModItems0, Items, ModItems) },
-		{ Module1 = module_imports(ModuleName, ModAncestors,
+		{ Module1 = module_imports(FileName, ModuleName, ModAncestors,
 				ModInterfaceDeps, ModImplementationDeps,
 				ModIndirectDeps, ModPublicChildren,
 				ModFactDeps, ModItems, ModError) },
@@ -2507,7 +2646,7 @@
 		Module, Module) --> [].
 process_module_long_interfaces([Import | Imports], Ext, IndirectImports0,
 		IndirectImports, Module0, Module) -->
-	{ Module0 = module_imports(ModuleName, ModAncestors,
+	{ Module0 = module_imports(FileName, ModuleName, ModAncestors,
 				ModInterfaceImports, ModImplementationImports0,
 				ModIndirectImports, ModPublicChildren,
 				ModFactDeps, ModItems0, ModError0) },
@@ -2546,7 +2685,7 @@
 		{ list__append(IndirectImports2, IndirectUses1,
 			IndirectImports3) },
 		{ list__append(ModItems0, Items, ModItems) },
-		{ Module1 = module_imports(ModuleName, ModAncestors,
+		{ Module1 = module_imports(FileName, ModuleName, ModAncestors,
 				ModInterfaceImports, ModImplementationImports,
 				ModIndirectImports, ModPublicChildren,
 				ModFactDeps, ModItems, ModError) },
@@ -2687,7 +2826,7 @@
 		IndirectImports, IndirectImports, Module, Module) --> [].
 process_module_short_interfaces([Import | Imports], Ext, 
 		IndirectImports0, IndirectImports, Module0, Module) -->
-	{ Module0 = module_imports(ModuleName, ModAncestors,
+	{ Module0 = module_imports(FileName, ModuleName, ModAncestors,
 			ModInterfaceDeps, ModImplementationDeps,
 			ModIndirectImports0, ModPublicChildren, ModFactDeps,
 			ModItems0, ModError0) },
@@ -2717,7 +2856,7 @@
 		{ list__append(IndirectImports0, Imports1, IndirectImports1) },
 		{ list__append(IndirectImports1, Uses1, IndirectImports2) },
 		{ list__append(ModItems0, Items, ModItems) },
-		{ Module1 = module_imports(ModuleName, ModAncestors,
+		{ Module1 = module_imports(FileName, ModuleName, ModAncestors,
 			ModInterfaceDeps, ModImplementationDeps,
 			ModIndirectImports, ModPublicChildren, ModFactDeps,
 			ModItems, ModError) },
Index: scripts/Mmake.rules
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/Mmake.rules,v
retrieving revision 1.59
diff -u -r1.59 Mmake.rules
--- Mmake.rules	1998/05/26 09:48:29	1.59
+++ Mmake.rules	1998/05/27 01:19:23
@@ -108,6 +108,8 @@
 #-----------------------------------------------------------------------------#
 #
 # Rules for building interface files
+# WARNING: any changes here will probably need to be
+# duplicated in compiler/modules.m.
 #
 
 $(date0s_subdir)%.date0 : %.m
@@ -152,6 +154,8 @@
 #-----------------------------------------------------------------------------#
 #
 # Rules for compiling Mercury source files
+# WARNING: any changes here will probably need to be
+# duplicated in compiler/modules.m.
 #
 
 $(cs_subdir)%.c : %.m
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.29
diff -u -r1.29 Mmakefile
--- Mmakefile	1998/05/20 13:10:15	1.29
+++ Mmakefile	1998/05/27 02:09:48
@@ -78,6 +78,7 @@
 # Not working:
 # 	cycles - loops when compiled in a non-GC grade with --deforestation.
 # 	cycles2 - loops when compiled in a non-GC grade.
+#	nested, nested2 - sometimes fail if using parallel makes
 
 #-----------------------------------------------------------------------------#
 
Index: tests/hard_coded/nested.exp
===================================================================
RCS file: nested.exp
diff -N nested.exp
--- /dev/null	Wed May 27 12:06:04 1998
+++ nested.exp	Wed May 27 12:12:34 1998
@@ -0,0 +1,14 @@
+nested:child:hello
+nested:child:hello
+nested:child:hello
+nested:child2:hello
+t1 = nested:child:foo
+t2 = nested:child:foo
+t3 = nested:child:foo
+t4 = nested:child2:foo
+t5 = nested:child2:foo
+has_type_t1 = bar
+has_type_t2 = bar
+has_type_t3 = bar
+has_type_t4 = bar
+has_type_t5 = bar
Index: tests/hard_coded/nested.m
===================================================================
RCS file: nested.m
diff -N nested.m
--- /dev/null	Wed May 27 12:06:04 1998
+++ nested.m	Wed May 27 12:05:47 1998
@@ -0,0 +1,95 @@
+% "Hello World" in Mercury, using nested modules.
+
+:- module nested.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+%-----------------------------------------------------------------------------%
+
+:- module nested:child.
+:- interface.
+:- import_module io.
+
+:- type foo ---> bar ; baz(int).
+
+:- pred hello(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+hello --> io__write_string("nested:child:hello\n").
+
+:- end_module nested:child.
+
+%-----------------------------------------------------------------------------%
+
+:- module nested:child2.
+:- interface.
+:- import_module io.
+
+:- type foo ---> bar ; baz(int).
+
+:- pred hello(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+hello --> io__write_string("nested:child2:hello\n").
+
+:- end_module nested:child2.
+
+%-----------------------------------------------------------------------------%
+
+% now we're back in the parent module.
+
+:- import_module nested:child.
+:- use_module nested:child2.
+:- import_module std_util, require.
+
+:- type t1 == nested:child:foo.
+:- type t2 == child:foo.
+:- type t3 == foo.
+:- type t4 == nested:child2:foo.
+% :- type t5 == child2:foo.	% XXX mixing of use_module and import_module
+				% is not yet supported.
+:- type t5 == nested:child2:foo.
+
+main -->
+	nested:child:hello,
+	child:hello,
+	hello,
+	nested:child2:hello,
+	% child2:hello,		% XXX mixing of use_module and import_module
+				% is not yet supported.
+
+	print("t1 = "), print(type_of(has_type_t1)), nl,
+	print("t2 = "), print(type_of(has_type_t2)), nl,
+	print("t3 = "), print(type_of(has_type_t3)), nl,
+	print("t4 = "), print(type_of(has_type_t4)), nl,
+	print("t5 = "), print(type_of(has_type_t5)), nl,
+
+	print("has_type_t1 = "), print(has_type_t1), nl,
+	print("has_type_t2 = "), print(has_type_t2), nl,
+	print("has_type_t3 = "), print(has_type_t3), nl,
+	print("has_type_t4 = "), print(has_type_t4), nl,
+	print("has_type_t5 = "), print(has_type_t5), nl,
+
+	{ true }.
+
+:- func has_type_t1 = t1.
+:- func has_type_t2 = t2.
+:- func has_type_t3 = t3.
+:- func has_type_t4 = t4.
+:- func has_type_t5 = t5.
+
+has_type_t1 = nested:child:bar.
+has_type_t2 = child:bar.
+has_type_t3 = bar.
+has_type_t4 = nested:child2:bar.
+% has_type_t5 = child2:bar.  % XXX mixing of use_module and import_module
+			     % is not yet supported.
+has_type_t5 = nested:child2:bar.
+
+:- end_module nested.
Index: tests/hard_coded/nested2.exp
===================================================================
RCS file: nested2.exp
diff -N nested2.exp
--- /dev/null	Wed May 27 12:06:04 1998
+++ nested2.exp	Wed May 27 12:11:30 1998
@@ -0,0 +1,10 @@
+nested2:hello
+nested2:hello
+t1 = nested2:foo
+t2 = nested2:foo
+t3 = nested2:foo
+t4 = nested2:foo
+has_type_t1 = bar
+has_type_t2 = bar
+has_type_t3 = baz(42)
+has_type_t4 = baz(42)
Index: tests/hard_coded/nested2.m
===================================================================
RCS file: nested2.m
diff -N nested2.m
--- /dev/null	Wed May 27 12:06:04 1998
+++ nested2.m	Wed May 27 12:10:34 1998
@@ -0,0 +1,61 @@
+% Another test case to test nested modules.
+
+:- module nested2.
+:- interface.
+:- import_module io.
+
+%-----------------------------------------------------------------------------%
+
+:- module nested2:child.
+:- interface.
+
+% module `io' is imported in nested2
+
+:- type t1 == foo.
+:- type t2 == nested2:foo.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+:- import_module std_util.
+
+:- type t3 == foo.
+:- type t4 == nested2:foo.
+
+:- func has_type_t1 = t1.
+:- func has_type_t2 = t2.
+:- func has_type_t3 = t3.
+:- func has_type_t4 = t4.
+
+has_type_t1 = bar.
+has_type_t2 = nested2:bar.
+has_type_t3 = baz(42).
+has_type_t4 = nested2:baz(42).
+
+main -->
+	nested2:hello,
+	hello,
+
+	print("t1 = "), print(type_of(has_type_t1)), nl,
+	print("t2 = "), print(type_of(has_type_t2)), nl,
+	print("t3 = "), print(type_of(has_type_t3)), nl,
+	print("t4 = "), print(type_of(has_type_t4)), nl,
+
+	print("has_type_t1 = "), print(has_type_t1), nl,
+	print("has_type_t2 = "), print(has_type_t2), nl,
+	print("has_type_t3 = "), print(has_type_t3), nl,
+	print("has_type_t4 = "), print(has_type_t4), nl.
+
+:- end_module nested2:child.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- type foo ---> bar ; baz(int).
+
+:- pred hello(io__state::di, io__state::uo) is det.
+
+hello --> print("nested2:hello\n").
+
+:- end_module nested2.

-- 
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