[Oberon] IMPORT Modules: why does order matter?
Andreas Pirklbauer
andreas_pirklbauer at yahoo.com
Mon Mar 4 09:12:05 CET 2019
> One day, the implementor of X and Y decides to do a refactoring, which
> does not change the interfaces of the modules, but leads to a dependency
> between those modules: X now imports Y.
>
>And suddenly, for no good reason, my module does not compile anymore.
If the “interface" of X does not change, you still be able to compile your module.
See section 16.6.2 of http://www.inf.ethz.ch/personal/wirth/ProjectOberon/PO.Applications.pdf .
Imported types can by re-exported, and their imports may be hidden.
Consequently, in Oberon, the “interface” of module X has, in fact, two components:
1) the “explicit" interface, which consists of all objects that are explicitly
exported by X (i.e. marked with an asterisk in the source text of X). Such
objects can by constants, types, variables or procedures.
2) the “hidden” interface, which consists of all those objects that X itself
has imported from another module Y *and* which are re-exported when X’s
symbol file is created. Such objects can only be types - for example when
module X declares a type T which is an extension of a type declared in Y,
or when X declares a record with a field whose type es declared in Y. Of
course, not all imported types are re-exported, only some.
There are multiple ways to handle these so-called "re-export conditions". The
approach chosen in FPGA Oberon is to make symbol files “self-contained”,
which means that any types T exported by, imported by X and then re-exported will
be included in the symbol file of X (module name Y, module key of Y, type name T).
The main motivation for this is to prevent the reading of the symbol file of Y when
only X is imported, but not Y (if Y’s symbol file *were* also read, it could trigger an
entire chain reaction of imports). It also means that for N imports exactly N symbol
files need to be read -> this makes import time *linear* in the number of imports).
There have been implementations of Oberon, where symbol files are read
*recursively*. This would also work, but it’s just not done in FPGA Oberon.
So, for a module which imports X, Y, this means:
1) If X does not re-export types imported from Y, its “interface” will not change
and you can still compile your module (even though, technically speaking,
X and Y are in the wrong order in the import list - but note: from the importing
module’s point of view, X and Y are still independent modules, the importing
module does not “know" that X in facts imports Y).
2) But if module X *does* re-export types imported from Y, then the interface
of X will also change when X is modified to import Y. And in *that* case, your
module will need to be recompiled - after changing the import list to Y, X.
More information about the Oberon
mailing list