The Semantics of Environments and Modules

This section describes the semantics of modules.

Description

The following sections provide a sketchy description of the semantics of modules.

Environments

Modules are bases on so called environments. Environments fulfill basically the same purpose as Smalltalk the single instance of SystemDictionary. They bind names that objects. Nearly all of the objects bound in an Environment are classes. All classes in an environment are immediately available to the code in all other classes bound the same environment by just mentioning their name. Obviously classes defined in an environment can be used by classes outside their environment only with some hassle.

Modules

Modules however provide means to make bound names available to other modules by exporting them. Exported symbols can be grouped into so called Interfaces. Otherwise Modules are just environments.

Interfaces

Interfaces can be imported by other modules.

When a module is created it starts out with two Interfaces:

API The Application Programming Interface

This interface should contain all the classes that are useful to the module’s clients, that is to classes that want use (instances of) the modules classes.

SPI The System Programming Interface

This interface is created as an alias of the API 1. It should contain all classes another module or class needs to enhance the functionality of the exporting module. Usually this is done by sub-classing these classes.

Some of Haver’s own modules defined so called UTIs (Unit Test Interfaces) that export classes which are not exported by the SPI. This should make white-box testing easier.

Note

Of course one can name a module’s interfaces as one pleases.

Imports

Modules can import an interface by creating an Import Specification. Import Specifications can import an interface of another module as a whole or they can explicitly select symbols of an interface. It also possible to specify, that you want to import all symbols of an interface and exclude it some of the exported symbols.

It is possible to import an interface more than once into a module.

Renaming

Symbols can be renamed upon export and import.

Packages

Each module, interface, exported symbol, import specification and imported symbol has an associated package, denoted by the package’s name. The default package name is the module name (of the interface, exported symbol, import …).

The export an import definitions are stored in the package-file of the package denoted by the package name.

Note

This makes it possible to specify a different package name for a Unit Testing Interface UTI and store the definition of this interface in a special unit test package.

The FileFinder package and its unit test package is a good example for this technique.

Formal Semantics

In the following section I try to give a formal definition for the semantics of modules and environments.

Environment Identifiers

The set of “Environment Identifiers” is a finite set of arbitrary Smalltalk objects.

Symbols

In essence symbols are immutable strings.

Symbols come in two variants:

Interned Symbols

“Interned Symbols” are those symbols known to the symbol class. Two interned symbols are identical wrt. to == when their character strings are equal wrt. =. This code snipped may serve as an explanation:

('one', 'two') asSymbol == 'onetwo' asSymbol

evaluates to true 2. Especially:

Symbol lookup: 'onetwo'

and:

Symbol lookup: 'one', 'two'

should evaluate to the same symbol: #onetwo

Uninterned Symbols

All other symbols are uninterned.

All symbols in Haver respond to the message environment. All interned symbols answer nil when the message environment is sent no them.

Local Symbols

Local symbols answer an environment identifier when the message environment is sent to them. This environment is not nil.

It follows from above propositions, that all local symbols are uninterned symbols.

Environments

“Environments” are mappings from local symbols to arbitrary Smalltalk objects. All symbols in the domain of the aforementioned mapping answer the environment when sent the message environment.

A local symbol can be created from any symbol by sending the message #forEnvironment: to it. The message needs an environment identifier as an argument.

Bound Symbol

A bound symbol is a symbol that is the domain of an environment’s mapping.

Modules

“Modules” are environments associated with two other sets, A set of interfaces and a set of import specifications.

Export Specification

An export specification is a mapping from a symbols to symbols.

Invalid Export Specifications

An “invalid export specification” is an export specification whose domain symbol is not bound in the module.

Interface

An interface is a set of export specifications.

Symbol Import Specification

An “symbol import specification” is mapping from an export specification to a symbol.

Import Specification

An import specification is a pair consisting of an interface and a set of symbol import specifications.

Invalid Import Specification

An “invalid import specification” is an “import specification” if its interface is not a member of any module’s set of interfaces.

Invalid Symbol Import Specification

An “invalid symbol import specification” is a symbol import specification if its export specification is not a member of any module’s interface or if its export specification is invalid.

The mappings in export specifications and symbol import specifications provide a means to rename a symbol on export and on import.

If the compiler uses #bindingOf: to find the binding of a global variable the binding is searched first in the environments then in Smalltalk.

In the case of an environment the binding only searched in the bindings of an environment 3.

In the case of a module the same is done. If this yields no binding, all valid symbol import specifications are searched for a matching name and the association in the exporting module is answered.

1

There is no UI-support to explicitly create interfaces that are aliases for other interfaces. Likewise new interfaces can not be created as an alias.

2

This should be true for every Smalltalk implementation.

3

Of course users may implement their own environment managers with vastly different semantics.