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