for review: add nested modules

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Mar 2 16:38:29 AEDT 1998


On 02-Mar-1998, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> >Add support for nested modules.
> 
> This looks pretty good. Just a few minor comments:

Thanks for your comments, Simon.

Here's a new diff which addresses all of Simon's and DJ's comments.
it is relative to my previous one, except for the
tests/invalid and tests/warning directories, where it is
relative to the main branch (since that was simpler).
The log message is the same as before, with the following addition:

	tests/invalid/Mmakefile:
	tests/invalid/missing_interface_import.m:
	tests/invalid/missing_interface_import.err_exp:
		Regression test to check that the compiler reports
		errors for missing `import_module' in the interface section.

I will commit this today.

diff -u old2/compiler/dead_proc_elim.m compiler/dead_proc_elim.m
--- old2/compiler/dead_proc_elim.m	Thu Feb 26 23:08:03 1998
+++ compiler/dead_proc_elim.m	Mon Mar  2 14:49:57 1998
@@ -39,10 +39,11 @@
 :- pred dead_pred_elim(module_info, module_info).
 :- mode dead_pred_elim(in, out) is det.
 
-:- type entity		--->	proc(pred_id, proc_id)
-			;	base_gen_info(module_name, string, int).
+:- type entity	
+	--->	proc(pred_id, proc_id)
+	;	base_gen_info(module_name, string, int).
 
-:- type needed_map ==	map(entity, maybe(int)).
+:- type needed_map == map(entity, maybe(int)).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
diff -u old2/compiler/intermod.m compiler/intermod.m
--- old2/compiler/intermod.m	Thu Feb 26 23:08:07 1998
+++ compiler/intermod.m	Mon Mar  2 16:15:06 1998
@@ -18,7 +18,6 @@
 %	- pragma declarations for the exported preds.
 %	- pragma c_header declarations if any pragma_c_code preds are written.
 % All these items should be module qualified.
-% Constructors should be explicitly type qualified. (XXX why?)
 %
 % This module also contains predicates to read in the .opt files and
 % to adjust the import status of local predicates which are exported for
@@ -350,6 +349,9 @@
 	call(PredId0, B, Args, D, MaybeUnifyContext, PredName0) - Info,
 	call(PredId, B, Args, D, MaybeUnifyContext, PredName) - Info, DoWrite)
 		-->
+	%
+	% Fully module-qualify the pred name
+	%
 	intermod_info_get_module_info(ModuleInfo),
 	intermod_info_get_var_types(VarTypes),
 	intermod_info_get_tvarset(TVarSet),
@@ -360,15 +362,14 @@
 		{ PredId = PredId0 },
 		{ PredName1 = PredName0 }
 	),	
-	(
-		{ PredName1 = qualified(_, _) },
-		{ PredName = PredName1 }
-	;
-		{ PredName1 = unqualified(Name) },
-		{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
-		{ pred_info_module(PredInfo, PredModule) },
-		{ PredName = qualified(PredModule, Name) }
-	),
+	{ unqualify_name(PredName1, UnqualPredName) },
+	{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
+	{ pred_info_module(PredInfo, PredModule) },
+	{ PredName = qualified(PredModule, UnqualPredName) },
+
+	%
+	% Ensure that the called predicate will be exported.
+	%
 	(
 		% We don't need to export complicated unification
 		% pred declarations, since they will be recreated when 
@@ -512,8 +513,7 @@
 	intermod__gather_proc_modes(ModuleInfo, ModeDefns,
 				UserInstDefns, Modes).
 
-	% Check if the functor is a function call, a higher-order
-	% term, or an unqualified symbol. If so, module qualify.
+	% Fully module-qualify the right-hand-side of a unification.
 	% For function calls and higher-order terms, call intermod__add_proc
 	% so that the predicate or function will be exported if necessary.
 intermod__module_qualify_unify_rhs(LVar, functor(Functor0, Vars),
@@ -549,7 +549,7 @@
 	->
 		%
 		% Yes, it is a function call.
-		% Module-qualify it.
+		% Fully module-qualify it.
 		% Make sure that the called function will be exported.
 		%
 		{ Functor = cons(QualifiedFuncName, Arity) },
@@ -574,7 +574,7 @@
 			TVarSet, ArgTypes, ModuleInfo, PredId, _ProcId) },
 		intermod_info_add_proc(PredId, DoWrite),
 		%
-		% Module-qualify it.
+		% Fully module-qualify it.
 		%
 		{ unqualify_name(PredName, UnqualPredName) },
 		{ predicate_module(ModuleInfo, PredId, Module) },
@@ -582,18 +582,24 @@
 		{ Functor = cons(QualifiedPredName, Arity) }
 	;
 		%
-		% Is it an unqualified functor symbol?
+		% Is it a functor symbol for which we can add
+		% a module qualifier?
 		%
-		{ Functor0 = cons(unqualified(ConsName), ConsArity) },
+		{ Functor0 = cons(ConsName, ConsArity) },
 		{ map__lookup(VarTypes, LVar, VarType) },
 		{ type_to_type_id(VarType, TypeId, _) },
 		{ TypeId = qualified(TypeModule, _) - _ }
 	->
-		{ Functor = cons(qualified(TypeModule, ConsName), ConsArity) },
+		%
+		% Fully module-qualify it
+		%
+		{ unqualify_name(ConsName, UnqualConsName) },
+		{ Functor = cons(qualified(TypeModule, UnqualConsName),
+				ConsArity) },
 		{ DoWrite = yes }
 	;
-		% XXX for (perhaps partially) qualified functor symbols,
-		% should we still add the module qualifier from the type?
+		% It is a constant of a builtin type.
+		% No module qualification needed.
 		{ Functor = Functor0 },
 		{ DoWrite = yes }
 	).
diff -u old2/compiler/mercury_compile.m compiler/mercury_compile.m
--- old2/compiler/mercury_compile.m	Thu Feb 26 23:08:08 1998
+++ compiler/mercury_compile.m	Mon Mar  2 15:34:37 1998
@@ -149,11 +149,11 @@
 		% command-line arguments, because it would confuse
 		% the mapping between module names and file names.
 		io__progname("mercury_compile", ProgName),
-		io__write_string(ProgName),
-		io__write_string(": Error in command-line argument `"),
-		io__write_string(PathName),
-		io__write_string("':\n"),
-		io__write_string("arguments may not contain directory names.\n")
+		io__write_strings([
+			ProgName, ": Error in command-line argument `",
+			PathName, "':\n",
+			"arguments may not contain directory names.\n"]),
+		io__set_exit_status(1)
 	).
 
 :- pred process_module_2(module_name, io__state, io__state).
@@ -402,7 +402,14 @@
 				    "dependencies for module `",
 				    ModuleString, "'.\n",
 				    "  Run `mmake ", BaseFileName, ".depend' ",
-				    "to remake the dependencies.\n"])
+				    "to remake the dependencies.\n"]),
+				globals__io_lookup_bool_option(halt_at_warn,
+					Halt),
+				( { Halt = yes } ->
+					io__set_exit_status(1)
+				;
+					[]
+				)
 			;
 				[]
 			)
diff -u old2/compiler/options.m compiler/options.m
--- old2/compiler/options.m	Thu Feb 26 23:08:10 1998
+++ compiler/options.m	Mon Mar  2 15:35:40 1998
@@ -1256,7 +1256,6 @@
 	io__write_string("\t--make-priv-int, --make-private-interface\n"),
 	io__write_string("\t\tWrite the private interface to `<module>.int0'.\n"),
 	io__write_string("\t\tThis option should only be used by mmake.\n"),
-	io__write_string("\t--make-opt-int, --make-optimization-interface\n"),
 	io__write_string("\t--make-short-int, --make-short-interface\n"),
 	io__write_string("\t\tWrite the unqualified short interface to `<module>.int3'.\n"),
 	io__write_string("\t\tThis option should only be used by mmake.\n"),
diff -u old2/compiler/prog_io.m compiler/prog_io.m
--- old2/compiler/prog_io.m	Thu Feb 26 23:08:10 1998
+++ compiler/prog_io.m	Mon Mar  2 16:20:39 1998
@@ -455,11 +455,19 @@
 	    % then issue a warning (if warning enabled), and
 	    % insert an implicit `:- module ModuleName' decl.
 	    %
-	    { term__context_init(SourceFileName, 1, FirstContext) },
-	    { maybe_add_warning(WarnMissing, MaybeFirstTerm, FirstContext,
-		"module should start with a `:- module' declaration",
-		[], Messages0) },
-
+	    { MaybeFirstItem = ok(_FirstItem, FirstContext0) ->
+		FirstContext = FirstContext0
+	    ;
+	        term__context_init(SourceFileName, 1, FirstContext)
+	    },
+	    { WarnMissing = yes ->
+		dummy_term_with_context(FirstContext, FirstTerm),
+		add_warning(
+			"module should start with a `:- module' declaration",
+			FirstTerm, [], Messages0)
+	    ;
+		Messages0 = []
+	    },
 	    { ModuleName = DefaultModuleName },
 	    { make_module_decl(ModuleName, FirstContext, FixedFirstItem) },
     
diff -u old2/compiler/type_util.m compiler/type_util.m
--- old2/compiler/type_util.m	Thu Feb 26 23:08:13 1998
+++ compiler/type_util.m	Mon Mar  2 15:52:43 1998
@@ -368,11 +368,16 @@
 
 %-----------------------------------------------------------------------------%
 
-	% the checks for type_info and base_type_info
+	% The checks for type_info and base_type_info
 	% are needed because those types lie about their
 	% arity; it might be cleaner to change that in
 	% mercury_builtin.m, but that would cause some
 	% bootstrapping difficulties.
+	% It might be slightly better to check for mercury_builtin:type_info
+	% etc. rather than just checking the unqualified type name,
+	% but I found it difficult to verify that the constructors
+	% would always be fully module-qualified at points where
+	% type_is_no_tag_type/3 is called.
 
 type_is_no_tag_type(Ctors, Ctor, Type) :-
 	Ctors = [Ctor - [_FieldName - Type]],
diff -u old2/doc/reference_manual.texi doc/reference_manual.texi
--- old2/doc/reference_manual.texi	Thu Feb 26 23:08:56 1998
+++ doc/reference_manual.texi	Mon Mar  2 16:01:14 1998
@@ -2457,9 +2457,9 @@
 A @samp{:- interface.} declaration indicates
 the start of the module's interface section:
 this section specifies the entities that are exported by this module.
-Mercury provides support for abstract data types, since the
-definition of a type may be kept hidden, with only the type
-name being exported.
+Mercury provides support for abstract data types, by allowing the
+definition of a type to be kept hidden, with the interface
+only exporting the type name.
 The interface section can contain declarations or definitions of types,
 definitions of typeclasses, typeclass instances, data constructors,
 instantiation states, and modes,
@@ -2474,11 +2474,11 @@
 The implementation section must contain definitions
 for all abstract data types, functions, predicates, and
 sub-modules exported by the module,
-as well for all local types, functions, predicates, and sub-modules.
+as well as for all local types, functions, predicates, and sub-modules.
 The implementation section can be omitted if it is empty.
 
 The module may optionally end with a @samp{:- end_module @var{ModuleName}}
-declaration; the name specified in the @samp{end_module} be the
+declaration; the name specified in the @samp{end_module} must be the
 same as that in the corresponding @samp{module} declaration.
 
 @c should we mention multipart interfaces and implementations?
@@ -2488,7 +2488,7 @@
 then it must explicitly import those modules using one or more 
 @samp{:- import_module @var{Modules}} or @samp{:- use_module @var{Modules}}
 declarations.  In both cases, @var{Modules} is a comma-separated list of
-(fully-qualified) module names.
+fully-qualified module names.
 These declarations may occur either in the interface or the implementation 
 section.  If the imported entities are used in the interface section,
 then the corresponding @code{import_module} or @code{use_module}
@@ -2613,7 +2613,7 @@
 @node Nested sub-modules
 @subsection Nested sub-modules
 
-Nested sub-modules within an module are delimited by
+Nested sub-modules within a module are delimited by
 matching @samp{:- module} and @samp{:- end_module} declarations.
 (Note that @samp{:- end_module} for nested sub-modules 
 are mandatory, not optional, even if the nested sub-module
@@ -2637,7 +2637,7 @@
 then there is an implicit definition with an empty implementation section
 for that sub-module (this will result in an error, if the interface
 section includes declarations but not definitions for any types,
-preds, modes, or (doubly) nested sub-modules).
+predicates, modes, or (doubly) nested sub-modules).
 
 @node Separate sub-modules
 @subsection Separate sub-modules
@@ -2685,7 +2685,11 @@
 However, declarations in a child module are not visible in the parent
 module or in "sibling" modules (other children of the same parent)
 unless the child is explicitly imported using a @samp{:- import_module}
-or @samp{:- use_module} declaration.
+or @samp{:- use_module} declaration. 
+
+Note that as mentioned previously, all @samp{:- import_module} and
+ at samp{:- use_module} declarations must use fully-qualified module
+names.
 
 @node Implementation bugs and limitations
 @subsection Implementation bugs and limitations
cvs diff: Diffing .
Index: unused_args_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/warnings/unused_args_test.exp,v
retrieving revision 1.4
diff -u -u -r1.4 unused_args_test.exp
--- unused_args_test.exp	1997/01/20 03:33:42	1.4
+++ unused_args_test.exp	1998/02/16 06:46:35
@@ -1,4 +1,4 @@
-unused_args_test.m:009: In predicate `unused_args_test:recursive'/3:
+unused_args_test.m:009: In predicate `unused_args_test:recursive/3':
 unused_args_test.m:009:   warning: argument 1 is unused.
-unused_args_test.m:011: In predicate `unused_args_test:nonrecursive'/1:
+unused_args_test.m:011: In predicate `unused_args_test:nonrecursive/1':
 unused_args_test.m:011:   warning: argument 1 is unused.
Index: unused_import.exp
===================================================================
RCS file: /home/mercury1/repository/tests/warnings/unused_import.exp,v
retrieving revision 1.3
diff -u -u -r1.3 unused_import.exp
--- unused_import.exp	1997/06/01 19:35:32	1.3
+++ unused_import.exp	1998/02/25 05:16:33
@@ -1,3 +1,4 @@
-unused_import.m:001: Warning: modules `float' and `list'
+unused_import.m:001: In module `unused_import':
+unused_import.m:001:   warning: modules `float' and `list'
 unused_import.m:001:   are imported in the interface, but are not
 unused_import.m:001:   used in the interface.
cvs diff: Diffing .
Index: Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.12
diff -u -u -r1.12 Mmakefile
--- Mmakefile	1998/02/03 08:01:54	1.12
+++ Mmakefile	1998/03/02 04:25:04
@@ -24,6 +24,7 @@
 	inline_conflict.m \
 	io_in_ite_cond.m \
 	missing_det_decls.m \
+	missing_interface_import.m \
 	modes_erroneous.m \
 	mostly_uniq1.m \
 	mostly_uniq2.m \
@@ -59,6 +60,7 @@
 MCFLAGS-multisoln_func	=	--infer-types
 MCFLAGS-any_mode	=	--infer-types
 MCFLAGS-duplicate_modes	=	--verbose-error-messages
+MCFLAGS-missing_interface_import = --make-interface
 
 DEPS=		$(SOURCES:%.m=%.dep)
 DEPENDS=	$(SOURCES:%.m=%.depend)
Index: errors.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/errors.err_exp,v
retrieving revision 1.3
diff -u -u -r1.3 errors.err_exp
--- errors.err_exp	1997/06/29 23:24:35	1.3
+++ errors.err_exp	1998/03/02 05:18:48
@@ -1,8 +1,8 @@
-errors.m:001: Warning: module should start with a `:- module' declaration.
+errors.m:010: Warning: module should start with a `:- module' declaration.
 errors.m:060: Error: free type parameter in RHS of type definition: f(_0).
 errors.m:061: Error: free type parameter in RHS of type definition: f(_0).
-errors.m:000: Warning: module `int' is imported using both
-errors.m:000:   `:- import_module' and `:- use_module' declarations.
+errors.m:001: Warning: module `int' is imported using both
+errors.m:001:   `:- import_module' and `:- use_module' declarations.
 errors.m:051: In definition of type `errors:du_type_which_references_undefined_type'/0:
 errors.m:051:   error: undefined type `undefined_type'/0.
 errors.m:053: In definition of type `errors:eqv_type_which_references_undefined_type'/0:
Index: missing_interface_import.err_exp
===================================================================
RCS file: missing_interface_import.err_exp
diff -N missing_interface_import.err_exp
--- /dev/null	Mon Mar  2 16:28:13 1998
+++ missing_interface_import.err_exp	Mon Mar  2 15:25:31 1998
@@ -0,0 +1,8 @@
+missing_interface_import.m:007: In definition of type `missing_interface_import:bar'/0:
+missing_interface_import.m:007:   error: undefined type `tree234'/2.
+missing_interface_import.m:009: In definition of predicate `missing_interface_import:p'/1:
+missing_interface_import.m:009:   error: undefined type `std_util:univ'/0.
+missing_interface_import.m:010: In definition of predicate `missing_interface_import:q'/1:
+missing_interface_import.m:010:   error: undefined type `list'/1.
+`missing_interface_import.int' not written.
+For more information, try recompiling with `-E'.
Index: missing_interface_import.m
===================================================================
RCS file: missing_interface_import.m
diff -N missing_interface_import.m
--- /dev/null	Mon Mar  2 16:28:13 1998
+++ missing_interface_import.m	Mon Mar  2 15:26:45 1998
@@ -0,0 +1,20 @@
+% Regression test: the Mercury compiler of Mon Mar 2, 1998
+% failed to report an error for this test case.
+
+:- module missing_interface_import.
+:- interface.
+
+:- type bar == map(int, int).
+
+:- pred p(std_util__univ::in) is det.
+:- pred q(list(int)::in) is det.
+
+:- implementation.
+
+% These import_module and use_module declarations should be in the
+% interface section.
+:- import_module list, map.
+:- use_module std_util.
+
+p(_).
+q(_).
-- 
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