[mercury-users] Modules, Submodules and Instances.
Fergus Henderson
fjh at cs.mu.OZ.AU
Sun Jan 31 09:50:52 AEDT 1999
On 30-Jan-1999, Ralph Becket <rwab1 at cam.sri.com> wrote:
> Fergus Henderson wrote on 30 Jan:
> >
> > > What exactly is the naming convention here? Under 0.8.1 I take it
> > > that bar and baz must be implemented in files foo.bar.m and foo.baz.m
> > > respectively.
> >
> > That's correct.
>
> That's interesting, because
> mercury-extras-0.8/complex_numbers/complex_numbers.m has the following
> body:
>
> :- module complex_numbers.
> :- interface.
> :- include_module complex, imag.
> :- include_module complex_imag, imag_complex.
> :- include_module float_imag, imag_float.
>
> but the modules imag etc. are all defined in files imag.m etc. I
> gather that complex_numbers.m is used in libarary generation? Is this
> a convenient abuse of the include_module directive or is something
> deeper going on here?
Oops, sorry -- what I wrote was *not* correct.
The correct answer is documented in the "Using the Mercury compiler"
chapter of the Mercury user's guide:
| Arguments to `mmc' may be either file names (ending in `.m'), or
| module names. For a module name such as `foo.bar.baz', the compiler
| will look for the source in files `foo.bar.baz.m', `bar.baz.m', and
| `baz.m', in that order.
One point that is not documented there is that you must use a fully qualified
name for either the file name, or the module name in the `:- module'
declaration, or both.
Unfortunately there are a few other places in the documentation where
file naming conventions are mentioned, and they were not updated when
this change (to allow non-fully-qualified file names if the module
name in the `:- module' declaration is fully-qualified) was made.
Thanks for letting us know about that -- I will modify the documentation
to fix the points mentioned in the previous two paragraphs.
> > > (3.2) Does it matter where the include_module declaration goes?
> > > Is there any difference between placing it in the interface or the
> > > implementation section?
> >
> > Yes, there is a difference. If you put the "include_module" declaration
> > in the implementation section, then that sub-module will be private;
> > it can only be used by its parent module and by other sub-modules
> > of the parent module.
>
> I'm slightly confused here. I was under the impression that
> include_module only declares a module to be a sub-module. The
> name-space, however, is actually extended by use_/import_module.
That's correct.
The placement of the `include_module' declaration affects the access
(public/private), but not the visibility. To make something visible,
that something needs to be accessible, and you also need to use
a use_/import_module declaration.
> Consider
>
> :- module foo.
> :- interface.
> :- include_module foo__bar.
> % At this point, we only know that foo__bar
> % is a sub-module, we don't have access to
> % its interface.
I think you may be confusing access (i.e. permission) with visibility
here. Both `foo' and modules which import `foo' do have permission to
access the interface to `foo__bar'. However, the declarations in
`foo__bar' are not yet visible, since you haven't given a `use_module'
or `import_module' declaration for `foo__bar'.
> If foo's interface goes on to to say
>
> :- import_module foo__bar.
> % Now foo__bar's interface is part of foo's
> % interface.
> then the interface of foo includes the interface of foo__bar.
No, `foo__bar's interface was already part of `foo's interface.
All the `import_module' declaration does is to make the symbols
declared in that sub-module visible in `foo'. `import_module'
declarations are not transitive, so this declaration has no effect
on modules that import foo -- it only affects `foo' itself.
> So what
> is the effect of putting `:- include_module foo__bar' in the interface
> for foo, but not `:- import_module foo__bar'?
That would mean that modules which import `foo' can use things defined
in `foo__bar' (presuming they contain a use_/import_module declaration
for it, of course), but `foo' itself does not.
> > See the third item in the "Implementation bugs and limitations"
> > sub-section:
> >
> > | * When using nested modules, the Mercury build tool Mmake sometimes
> > | tries to build things in the wrong order and hence reports
> > | spurious errors about `.int*' files not being found. In these
> > | cases, simply typing `mmake' again will usually solve the problem.
>
> Mea culpa. What's the solution if a second mmake doesn't do the
> trick?
Use separate sub-modules rather than nested sub-modules.
(That is, put the sub-modules in a separate source file
included via `include_module', rather than textually
including them in the source of the parent module.)
> > Unfortunately there was a bug in 0.8 which meant that if the
> > end-module declaration for a sub-module is the last thing
> > in the containing module, the compiler would report a spurious error.
> > This bug was fixed in our development sources on Dec 17.
> > I've attached the patch. The work-around, if you need to use 0.8,
>
> 'fraid the patch never made it through.
I've attached it this time.
(But as you said, using the work-around of including an explicit
`end_module' declaration for the parent module is probably simpler.)
--
Fergus Henderson <fjh at cs.mu.oz.au> | "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh> | but source code lives forever"
PGP: finger fjh at 128.250.37.3 | -- leaked Microsoft memo.
-------------- next part --------------
Index: make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.279
retrieving revision 1.280
diff -u -u -r1.279 -r1.280
--- make_hlds.m 1998/12/06 23:43:43 1.279
+++ make_hlds.m 1998/12/16 17:24:16 1.280
@@ -259,6 +259,14 @@
report_warning("Warning: `external' declaration requires arity.\n"),
io__set_output_stream(OldStream, _)
)
+ ; { ModuleDefn = module(_ModuleName) } ->
+ report_unexpected_decl("module", Context),
+ { Status = Status0 },
+ { Module = Module0 }
+ ; { ModuleDefn = end_module(_ModuleName) } ->
+ report_unexpected_decl("end_module", Context),
+ { Status = Status0 },
+ { Module = Module0 }
;
{ Status = Status0 },
{ Module = Module0 },
@@ -4759,6 +4767,16 @@
%-----------------------------------------------------------------------------%
% Predicates to write out the different warning and error messages.
+
+:- pred report_unexpected_decl(string, prog_context, io__state, io__state).
+:- mode report_unexpected_decl(in, in, di, uo) is det.
+
+report_unexpected_decl(Descr, Context) -->
+ io__set_exit_status(1),
+ prog_out__write_context(Context),
+ io__write_string("Error: unexpected or incorrect `"),
+ io__write_string(Descr),
+ io__write_string("' declaration.\n").
:- pred multiple_def_error(sym_name, int, string, prog_context, prog_context,
io__state, io__state).
Index: prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.178
retrieving revision 1.179
diff -u -u -r1.178 -r1.179
--- prog_io.m 1998/11/20 04:08:56 1.178
+++ prog_io.m 1998/12/16 17:24:18 1.179
@@ -288,11 +288,18 @@
:- type module_end ---> no ; yes(module_name, prog_context).
-:- pred get_end_module(item_list, item_list, module_end).
-:- mode get_end_module(in, out, out) is det.
+:- pred get_end_module(item_list, module_name, item_list, module_end).
+:- mode get_end_module(in, in, out, out) is det.
-get_end_module(RevItems0, RevItems, EndModule) :-
+get_end_module(RevItems0, ModuleName, RevItems, EndModule) :-
(
+ %
+ % Note: if the module name in the end_module declaration
+ % does not match what we expect, given the source file name,
+ % then we assume that it is for a nested module, and so
+ % we leave it alone. If it is not for a nested module,
+ % the error will be caught by make_hlds.m.
+ %
RevItems0 = [
module_defn(_VarSet, end_module(ModuleName)) - Context
| RevItems1]
@@ -403,7 +410,7 @@
% check that it matches the initial module declaration (if any),
% and remove both of them from the final item list.
%
- { get_end_module(RevItems0, RevItems, EndModule) },
+ { get_end_module(RevItems0, ModuleName, RevItems, EndModule) },
{ list__reverse(RevMessages, Messages0) },
{ list__reverse(RevItems, Items0) },
check_end_module(EndModule,
More information about the users
mailing list