Path: utzoo!mnetor!uunet!munnari!mulga!lee
From: lee@mulga.oz (Lee Naish)
Newsgroups: comp.lang.prolog
Subject: Re: modules
Message-ID: <2747@mulga.oz>
Date: 10 May 88 03:17:09 GMT
Reply-To: lee@mulga.UUCP (Lee Naish)
Organization: Comp Sci, Melbourne Uni, Australia
Lines: 98
Keywords: another module scheme

The main uses of a module system are
	1) avoiding accidental name clashes, and
	2) protecting procedures from being called by anyone.

THEOREM: Every module system is either too complicated or
	 not powerful enough.

COROLLARY: It is impossible to get more than two people to agree on a
	   module system (the failure of the BSI module committee was
	   therefore inevitable).

Prolog module systems have to handle a bit more than module systems of
conventional languages because of the ways in which data/code can be
converted into other representations and converted back:

	1) name/2 converts between atoms (possibly in a particular
	   module) and strings.

	2) =.. (and functor/3) converts between atoms and functors with
	   different arities (possibly in a particular module).

	3) read/1 and write/1 (etc) convert between terms and text.

	4) call/1, clause/2 and assert/1 (etc) "convert" between code
	   and data.

We must determine exactly what these operations do (eg, whether they are
reversible) and if the language is changed to introduce extra arguments
to specify module names.

Quite a while back I made a proposal for a module scheme and discussed
it with various people at Melbourne uni (the result was inevitable).
A version of the scheme was even implemented.  One advantage is that it
requires no changes to the Prolog system - our implementation was a
preprocessor which could be used with any Edinburgh Prolog system.

The scheme is atom based (the arity of a functor is irrelevant).  The
basic idea is that at "compile" time, atoms are mapped to other atoms.

To avoid accidental name clashes, module names can be added to atom
names.  For example, atom 'join' in module 'tree_util' could be mapped to
'tree_util$join'.  To implement protection, atoms can be mapped to
"random" strings, for example, ' tree_util$join 417309467298353'.

Every occurrence of 'join' (with any arity) in module tree_util should
be changed.  A 'join' predicate or call in another module will (by
default) not be renamed, so clashes are avoided.  There is no way
another module can guess the "random" string an atom is mapped to
(the string may depend on when the module was compiled) so protection
is achieved (for watertight protection in any system current_predicate
etc must be modified also).

There are many ways you can define what atoms should be
renamed/encrypted.  One implementation we have accepts the following
syntax:

?- module tree_util : public([list_to_tree, tree_insert]).

list_to_tree([], nil).
.....
join(T0, T1, T) :-
....

?- endMod : tree_util.

This renames every atom which is the name of a procedure defined in the
module except list_to_tree and tree_insert (these two atoms are
unchanged).  There are two options on the preprocessor - one for simply
adding module names and one for adding random strings also.

Another possible syntax is:

:- module tree_util :
	public [list_to_tree, tree_insert],
	import [>= from term_comparison],
	entry [join],
	local [join_1].
....
:- end_module.

This could specify that >= is renamed 'term_comparison$>=', join is
renamed 'tree_util$join' and join_1 is renamed ' tree_util$join_1 78435'.

One advantage of specifying all atoms which are to be renamed is that
only one pass is needed.  The whole module system could be implemented
by using term_expansion.  Nested modules can also be handled very
easily.

One further feature which may occasionally be useful is to provide a
procedure to convert between the original atoms and the renamed versions.
To avoid name clashes and compromising protection, this procedure should
be renamed.  For example, the system could define an is_local procedure
(which is local) for a module:

' tree_util$is_local 76835'(join_1, ' tree_util$join_1 78435').
' tree_util$is_local 76835'(is_local, ' tree_util$is_local 76835').

	Lee Naish