Oberon || Library || Module Index || Search Engine || Definition || Module

Ulm's Oberon Library:


CompilerKeys - keys that identify dependencies of compiler-generated objects


TYPE Value = POINTER TO ValueRec;
TYPE ValueRec =
      time: Times.Time; (* date of creation *)
      unique1, unique2: INTEGER; (* hopefully unique *)
TYPE KeyRec =
      modname: ConstStrings.String;
      defsrcid, modsrcid: ConstStrings.String;
      genkey: Value;
      arch: Architectures.Architecture;
      archkey: Value;
TYPE SetRec = RECORD (PersistentDisciplines.ObjectRec) END;
VAR key: Keys.Key; (* for Key *)

PROCEDURE CreateValue(VAR value: Value);

PROCEDURE Create(VAR key: Key; modname: ConstStrings.String); PROCEDURE CreateCopy(VAR key: Key; orig: Key);

PROCEDURE ValueToString(value: Value; VAR string: ConstStrings.String); PROCEDURE StringToValue(string: Streams.Stream; VAR value: Value);

PROCEDURE CreateSet(VAR set: Set); PROCEDURE CreateSetCopy(VAR set: Set; orig: Set); PROCEDURE Incl(set: Set; key: Key); PROCEDURE InclSet(set, keys: Set); PROCEDURE Union(VAR set: Set; set1, set2: Set); PROCEDURE Lookup(set: Set; modname: ConstStrings.String; VAR key: Key) : BOOLEAN; PROCEDURE GetKeys(set: Set; VAR it: Iterators.Iterator); PROCEDURE Compatible(set1, set2: Set) : BOOLEAN; PROCEDURE CompatibleWith(key: Key; set: Set) : BOOLEAN; PROCEDURE CombineKeys(key1: Key; key2: Key; VAR combined: Key) : BOOLEAN;


CompilerKeys supports the identification of dependencies of compiler-generated objects. They allow to assure that all objects that are loaded into one address space are compatible to each other. The basic idea is simple: Every interface compiled gets a new key of its own and a set of keys it depends on (is empty if no modules are imported). Compiler objects generated from sources (definitions or modules) that other modules include the keys of the corresponding interface objects into their own set. Compatibility is given if there is never more than one key per module involved.

Example: Modules A, B, and C. B and C import from A. On compiling the public interfaces, the compiler generates the keys a1, b1, and c1 for A, B, and C, respectively. On compiling the modules, A has a key set of {a1}, B {a1, b1}, and C {a1, c1}. These three modules can be safely combined with a joint key set of {a1, b1, c1}. If A and B are recompiled but not C we would yield a key set of {a2} for A and {a2, b2} for B. A combination with the old object of C yields a key set of {a1, a2, b2, c1}. This key set contains two keys of module A (a1 and a2) and is therefore invalid because the modules and C were compiled for different interfaces of A. This example was simplified to show the general idea. CompilerKeys supports a model that differentiates architecture-dependent from architecture-independent keys and that honors the possibility of interface updates by the corresponding module (necessary to support Oberon with separated definition and module).

CreateValue creates a object of type CompilerKeys.Value that consists of a time stamp and two integer values returned by a pseudo random generator that are hopefully unique. Note that the pseudo random numbers are returned by RandomGenerators which allows better algorithms and better seed values to be plugged in. These objects provide uniqueness beyond that of source ids because the same source may be compiled using different compilation options and different environments.

Create creates an object of type CompilerKeys.Key for modname. With the exception of modname all components of key are set to NIL and should be initialized shortly thereafter. Later, keys are expected to remain constant. Instead CreateCopy may be used for copying and modifying a key while leaving its original untouched.

ValueToString and StringToValue convert a value (triple of timestamp and two random values) into a constant string and vice versa. This may be useful for conversion of keys into a human-readable representation (as done by cdbd, for example). Note, however, that both procedures expect the timestamp to be in a time range supported by Dates.

Key sets are collections of keys with a upper limit of one key per module. CreateSet may be used to create an empty key set. Later on, key sets may grow only in a consistent way using Incl, nclSet, and Union: Keys added must belong to modules not yet added, or they must be compatible upgrades from an architecture-independent to an architecture-dependent key. CreateSetCopy creates an independent copy of orig.

Lookup allows to lookup single keys by module and GetKeys permits to iterate all members of a key set.

Compatibility of key sets or key set extensions may be tested using Compatible (checking two sets against each other) and CompatibleWith (checking one key against a set). These tests are useful prior adding new keys or sets to an existing set as compatbility violations are treated as fatal errors (an event of a failed assertion would be raised).

CombineKeys may be used to check the compatibility of two single keys, and returns, if successful, the combination of them.

The exported variable key is a key of Keys defining a total order relation on objects of type CompilerKeys.Key that compares keys using its components in following order: module name (alphabetically), time stamp of architecture-independent key (using Operations.Compare), their architecture (alphabetically) and the second timestamp in case of architecture-dependent keys.


All BOOLEAN-valued functions return FALSE in case of errors or incompatibility. Assertions check that that keys to be included to a set are compatible to it.


classification of hardware architectures
operations for persistent objects
total order relations

Edited by: borchert, last change: 2000/04/06, revision: 1.2, converted to HTML: 2000/04/06

Oberon || Library || Module Index || Search Engine || Definition || Module