nested modules proposal

Peter Schachte pets at students.cs.mu.OZ.AU
Tue Feb 17 16:35:05 AEDT 1998


Firstly, I think this looks much simpler and cleaner than the previous
(package) approach. 

> 	A module may contain sub-modules, delimited by
> 	`:- module' and `:- end_module declarations'.

I assume you mean "`:- end_module' declarations" (note the single quotes).

Can the :- end_module declaration still be omitted for submodules written in
separate files?  How about for the last nested module in a file, eg:

	:- module foo.
	...
	:- module bar.
	...
	<eof>


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

I don't see the problem.  Under Quintus:

	| ?- current_op(X,Y,(:)).

	X = 600,
	Y = xfy ;

	no
	| ?- op(600,fy,(:)).

	yes
	| ?- X = a:b:c.

	X = a:b:c

	| ?- X = :a:b:c.

	X = :a:b:c 

The problem arises when you want a *postfix* and infix op of the same name. 


> 	The interface of a module does not include the implementations
> 	of any sub-modules defined in that module's interface.

Hmmm.  It seems quite odd to nest a module within another module's
*interface* section.  I asssume the reason to do that would be to export
the inner module's exports from the outer module.  I think it would be much
nicer to handle it the other way:  some kind of declaration in the
implementation section of the outer module indicating that the inner
module's exports are exported from the outer module.  E.g.,

	:- module foo.
	:- interface.
	:- export_module foo:bar.
	...
	:- implementation.
	:- module foo:bar.
	....

Better yet, use some sort of `:- public' declarations ;-).  In fact, the
nesting approach doesn't handle in any clean way I can think of what will
commonly be wanted:  each submodule has an interface to sibling submodules,
and a subset of that interface is made visible outside the parent module.

This raises another point:  one would like to be able to construct a module
from several submodules, but the the outside world shouldn't see how the
outer module is constructed.  E.g., I've got predicates m:m1:p1 and m:m2:p2,
but I'd like them to be visible to users of module m as m:p1 and m:p2.  This
is important to allow the designer of module m to change the implementation
later.  Sure, this can be done by writing a slew of pass-through predicates,
but this is pretty awful.  In fact, I would argue that users of module m
should never be able to refer to m:m1:p1 or m1:p1 at all.  I would argue
that you only want to be able to see the module hierarchy "above you" and at
your level, never below (or one level below, depending on what you think of
as your level).  So if there's a predicate :m1:m2:m3:p, and it's exported by
all three enclosing modules and imported into the current context, I should
be able to specify it as p or m1:p or :m1:p in the current context, but not
as m2:m3:p or m1:m2:m3:p or anything else.  Inside module m1, and in m2's
siblings, it should be referred to as p or m2:p or m1:m2:p or :m1:m2:p, but
no mention of m3 should be allowed.

Phew!

> 	Every module gets an implicit `:- import_module std' declaration,
> 	unless it contains an explicit `:- use_module std' declaration.

So then is there no way to be sure you're not using the standard library
(because you're using an alternative standard library instead)? 

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

Except that the normal Mercury source file restrictions apply: the included
file must be a single module (perhaps with modules nested within it).  It's
not a "normal" include at all.

Is the syntax for the module declaration at the top of the file for module
foo:bar:

	:- module foo:bar.
or
	:- module bar.
or
	:- module :foo:bar.

> 	The mapping between module names and file names is
> 	is implementation-dependent.

A fine idea, unless you're prepared to carefully consider all possible file
systems.  For starters, foo.bar.m is going to be tough under MS-DOG, and
separate directories won't work under VM/CMS.  And I shudder to think what
any of this means in my washing machine or toaster ;-).

> 	Mmake gets a new `--in-module' option.

This appears to conflict with your later comments about file/module naming,
suggesting that the file/module name would determine containing module(s). 
Why is this switch needed?  And how do you write the default mmake rule for
building .o files from .m's? 

What about allowing sibling modules to use or import one another?  I hope
this is allowed; it's pretty important.  Can a nested module m automatically
see everything imported/used into the parent module p, including what p
imports/uses/includes from sibling modules?

What does it mean to *import* a nested module?  Is this an error?




-Peter Schachte			| The secret of being miserable is to have the
pets at cs.mu.OZ.AU		| leisure to bother about whether you are
http://www.cs.mu.oz.au/~pets/	| happy or not. The cure is occupation.
PGP key available on request	| -- George Bernard Shaw 




More information about the developers mailing list