As we have seen, each Algol 68 source file contains either a particular program or a prelude packet. Prelude packets consist on the definition of a single top-level module, that is itself identified by a module indicant.
Consider for example a source file called trilean.a68 that
implements strong Kleene three-valued (“trilean”) logic. It does so
by the mean of a definition module called Trilean. A
sketch of such a file may look like this:
module Trilean =
def
pub mode Tril = int;
pub Tril dontknow = 0, yes = 1, no = 2;
pub prio AND3 = 3, OR3 = 3, XOR3 = 3;
pub op NOT3 = (Tril a) Tril:
(a + 1 | dontknow, no, yes);
C ... other definitions ... C
fed
The module indicant Trilean identifies the module. If we
now compile this file to an object file using GCC:
$ ga68 -c trilean.a68
The result of the compilation is an object file trilean.o, plus
some exports information which is placed in a section in the
object file, named .a68_exports. The exports information
describes the interface provided by the Trilean module
defined in the compilation unit. This includes all the modes,
identifiers, priorities, operators, etc, that are publicized by the
module. The particular encoding used to hold these exports is highly
compact and not easy readable by persons; instead, it is designed to
be read back by GCC when it builds another compilation unit that, in
turn, needs to access the Trilean module.
Consider the following sketched particular program that resides in a source file main.a68, and that uses trilean logic:
access Trilean
begin
C ... C
end
When this program gets compiled by GCC using ga68 -c
program.a68, the compiler finds the access clause and needs to locate
some exports for the module Trilean. To do so, it searches
in the modules search path, composed by the current working directory,
some system directories and all directories specified in -I
and -L options, looking for files called trilean.m68,
trilean.so, trilean.a and trilean.o, in that
order, where:
Is a stand-alone file expected to contain export data for one or more modules.
Is a DSO, or shared object, expected to contain a .a68_exports
section with exports data for one or more modules.
Is an archive, whose constituent object files may contain
.a68_exports sections with exports data for one or more
modules.
Is an object file expected to contain export data for one or more
modules in a .a68_exports section.
The files are tried in order, and if export data for the requested
module Trilean is found, it is read in, decoded, and used
to compile main.a68 into main.o.
The last step in obtaining an executable for our program would be to
use GCC to do a link like ga68 trilean.o main.o -o main.
Module indicants such as Trilean are bold words in the
language. This means that, independently of the stropping regime
used, they are constituted by a bold letter followed by a sequence of
zero or more bold letters and digits. Using the modern stropping
supported by the GNU Algol 68 compiler, this means that all of
Trilean, TRILEAN and Tri_lean denote
exactly the same module indicant, trilean.
The mapping from module indicant to the “base name” used to locate
the module exports is quite straightforward: the bold letters are
transformed to lower-case letters, and the bold digits are just normal
digits. Therefore, the exports for the module
GRAMP_Grammar would looked in files
grampgrammar.m68, libgrampgrammar.so, etc.
But often this default, straightforward mapping, is not what we need.
Suppose for example that a shared object installed in the system,
liba68goodies.so, provides many facilities in the form of
several modules, including a Trilean module. We want to
use the trilean implementation of liba68goodies in our program
main.a68. If we just access Trilean GCC will
look for trilean.m68 etc, but wont even consider looking in
liba68goodies.so. Accessing A68Goodies is obviously
not a solution, as the module we want is Trilean and there
may not even be a module called A68Goodies in
liba68goodies.so.
The solution for this is to use the modules map of the compiler. This map is an association or map between module indicants and base-names. When it comes to access some module, the compiler looks in the map. If there is an entry for the module’s indicant, then it fetches the base-name to use for looking for the module’s export data. If there is not an entry for the module’s indicant then the default, straightforward mapping described above is attempted.
By default the map is empty, but we can add entries by using the -fmodules-map= and -fmodules-map-file= command-line options. The first option expects entries to be added to the map in a string in the command-line, whereas the second option expects the name of a file containing the entries to add to the map. In both cases the format describing the entries is exactly the same (see Module search options).
In our case, we could compile our main program specifying an entry in the map telling the compiler where to find the trilean and logging modules:
$ ga68 -fmodules-map="a68goodies=Trilean,Logger" -c main.a68