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 :class:`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` [#]_. 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 |Havers| 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. .. _FileFinder package: https://hg.sr.ht/~cy-de-fect/HaverOnCuis/browse/haver/packaging/FileFinder.pck.st .. _unit test package: https://hg.sr.ht/~cy-de-fect/HaverOnCuis/browse/haver/packaging/FileFinderTest.pck.st 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` [#]_. 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 [#]_. 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. .. [#] 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. .. [#] This should be true for every Smalltalk implementation. .. [#] Of course users may implement their own environment managers with vastly different semantics.