nested modules proposal (was: packages proposal)
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Feb 13 02:01:06 AEDT 1998
I spent a lot of time thinking about my packages proposal last night
(couldn't sleep, actually), and I have come up with a new, simpler
proposal which I think would in fact be easier to implement.
So scrap the previous proposal, and replace it with this one.
My new proposal is just this:
1. Allow nested modules (and hence compound module qualifiers).
2. Allow separate compilation of nested modules.
[I spend most of today working on this proposal, saving (using :w in vi)
regularly. Finally I finished it, and hit "send" in mutt...
at which point --- it being by then just past midnight on the morning
of Friday the 13th --- mutt, murlibobo, OSF, and/or evil sysadmins
managed to conspire to NOT send it, NOT save it to my outgoing mail
folder, and to DELETE the copy in /tmp. AAAAAAAArrrrrgh!!!!!!!!!!
This copy is reconstructed from a version about 8 hours out-of-date.
It's not as complete as I would like...]
1. Nested modules.
------------------
Syntax:
A module may contain sub-modules, delimited by
`:- module' and `:- end_module declarations'.
Module names themselves be module-qualified.
Notes:
This implies that module qualifiers may contain a list of
module names (eventually using the syntax `m1.m2.foo', but for
the moment using the syntax `m1:m2:foo' or `m1__m2__foo')
rather than just a single module name.
(We should also add some new syntax for fully-qualified
module names, e.g. `:m1:m2:foo', but I can't think
of a workable syntax for it.)
Semantics:
Any declarations visible in the containing module are fully visible
within the sub-modules. However, declarations in a sub-module
are not visible in other sub-modules unless that sub-module
has been explicitly imported using a `:- use_module' or a
`:- import_module' declaration.
Within the containing module, declarations in the sub-module
interfaces may be accessed using module-qualified notation
(as if the module containined an implicit `:- use_module'
declaration to allow it to use the sub-module).
Declarations in sub-modules may be accessed using unqualified
notation only if the sub-module is explicitly imported using
`:- import_module'.
Symbol names can be partially-module-qualified; that is,
they may include only a trailing subsequence of the
components in the fully-qualified module name.
For example, if modules whose fully-qualified module
names are `foo', `bar:foo' and `baz:foo' have all been
imported, then a module-qualified symbol name `foo:quux' may
refer to the fully-qualified symbol `foo:quux', `bar:foo:quux',
or `baz:foo:quux'. The type checker will attempt to resolve
such ambiguities using the ordinary ambiguity resolution rules.
The interface of a module does not include the implementations
of any sub-modules defined in that module's interface.
Every module gets an implicit `:- import_module std' declaration,
unless it contains an explicit `:- use_module std' declaration.
2. Separate compilation of nested modules
------------------------------------------
Syntax:
:- include_module <ModuleName>.
Semantics:
An include_module definition references a sub-module
defined in a different source file.
The language semantics of an `include_module' declaration
is that it is exactly equivalent to replacing the
`import_module' declaration with the module to which it
refers. However, implementations should support
separate compilation for non-nested sub-modules.
The mapping between module names and file names is
is implementation-dependent.
-----------------------------------------------------------------------------
That's it!
-----------------------------------------------------------------------------
Implementation:
The implementation should be pretty simple.
Mmake gets a new `--in-module' option.
When compiling sub-modules, the compiler basically just reads
in the source for the containing module.
Nested modules are compiled (parse tree -> LLDS) one at a time,
and then the LLDS fragments are concatenated to get a single C
file.
<insert some hand-waving here>
[I had a more detailed description of this, but... <grumble>.]
File naming conventions:
When creating the dependencies, the compiler needs to
find the source code for non-nested sub-modules.
If module `foo' is defined in file `foo.m',
then module `foo:bar' should be defined in
file `foo/bar.m',`foo.bar.m', or just plain `bar.m'.
The compiler should search for it in each of those
places in turn (in that order).
A similar algorithm should be used to find interface files.
Conversely, when compiling a module, the compiler
needs to read in the source for its containing module(s).
If the source file name for the submodule `<mp1><mp2>foo:bar'
ends in `<mp2>foo.bar.m' (here <mp1> and <mp2> stand for
arbitrary module prefixes, possibly empty), then the containing
package should be in file `<mp2>foo.m'. If not, then it should
be in either `../foo.m' or `./foo.m'.
[I had a longer description here, but... <grumble>.]
Examples:
% library/std.m
:- module std.
:- interface.
:- include_module list, string, char, term, term_io. % ...
:- implementation.
:- include_module debugger_interface, lexer, parser.
:- end_module std.
% compiler/hlds.m
:- module hlds.
:- interface.
:- include_module hlds:data, hlds:goal, hlds:pred, hlds:module.
:- include_module hlds:out.
% the module qualifiers above are optional.
:- end_module hlds.
% compiler/hlds.goal.m:
:- module hlds.goal. % the module qualifier here is optional
...
:- end_module.
Comments?
--
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