In all the examples seen so far the modules were accessed just once. In these cases, accessing the module via an access-clause caused the activation of the module.
Activating a module involves elaborating all the declarations and units that conform its prelude. Depending on the particular module definition that gets activated, this may involve all sort of side effects, such as allocating space for values and initializing them, opening files, etc. Once the modules specified in the access clause are successfully activated, the controlled clause gets elaborated itself, within the reach of all the publicized definitions by the activated modules as we saw in the last section. Finally, once the controlled clause has been elaborated, the module gets revoked by elaborating the serial clause in its postlude.
However, nothing prevents some given definition module to be accessed
more than once in the same program. The following program, that makes
use of the logger module, exemplifies this:
access logger
begin originator := argv (1);
log ("executing program");
c ... c
access logger (originator := argv (1) + ":subtask";
log ("doing subtask")
c ... c)
end
In this program the module logger is accessed twice. The
code is obviously written assuming that the inner access clause
triggers a new activation of the logger module, allocating
new storage and executing its prelude. This would result in the
following log contents:
a.out: beginning of log a.out: executing program a.out:subtask: beginning of log a.out:subtask: doing subtask a.out:subtask: end of log a.out: end of log
However, this is not what happens. The module gets only activated once, as the result of the outer access clause. The inner access clause just makes the publicized indicators visible in its controlled clause. The actual resulting log output is:
a.out: beginning of log a.out: executing program a.out:subtask: doing subtask a.out:subtask: end of log
Which is not what we intended. Modules are not classes. If we wanted the logger to support several originators that can be nested, we would need to add support for it in the definition module. Something like:
module logger =
def int fd = stderr, max originators = 10;
int orig := 0;
[max originators]string originators;
pub proc push originator = (string str) void:
(assert (orig < max originators);
orig +:= 1;
originators[orig] := str);
pub proc pop originator = void:
(assert (max originators > 0);
orig -:= 1);
pub proc log = (string msg) void:
fputs (fd, (originator[orig] /= "" | ": ") + msg + "\n");
log ("beginning of log\n");
postlude
log ("end of log\n");
fed
Note how in this version of logger originators acts
as a stack of originator strings, and it is not publicized. The
management of the stack is done via a pair of publicized procedures
push originator and pop originator. Our program will
now look like:
access logger
begin push originator (argv (1));
log ("executing program");
c ... c
access logger (push originator ("subtask");
log ("doing subtask")
c ... c;
pop originator)
end
And the log output is:
a.out: beginning of log a.out: executing program a.out:subtask: doing subtask a.out: end of log
————————————————————–
module-indications are used to find interface-definitions of modules:
ACCESS FOO SKIP
Looks for (in order):
foo.m68 foo.o libfoo.so
Should we use instead:
ACCESS "foo" SKIP
That would use for module indicators the same syntax than hole indicators.
Modules get accessed, invoked and revoked.
Access clauses:
: ACCESS A, B <enclosed clause>
Where A and B are “revelations”.
In
: MODULE A = ACCESS B DEF ... FED
Doesn’t reveals any contents of B. Whereas in:
: MODULE A = ACCESS PUB B DEF .. FED
The module A is also revealing B’s public declarations. So accessing A provides access to B.
User-defined preludes go to the user-prelude.
Invocation and revocation:: How modules are executed.
It is possible for a definition module to not publicize any definition. Such modules would be used only for the side effects produced from executing the prelude and postlude when the module gets invoked and revoked. XXX: provide an example?
XXX