#5. Modules. A module is a predefined net with a designated head node. Such a module can be kept in the system library under some name. There is an operation of fetching the module, that builds a new copy of it and returns the node copied from the head node. Fetching allows to include in the net a lot of information at a time and can be used instead of procedure calls.

Back to the sample procedure of #3, we build the following module named BABY (pic.4). The call to the procedure BIRTH of #3 can now be replaced (with slight changes) by the following statements
LOADNET BABY,TO=BB
* fetch the module, the head node of the copy will be
* assigned to BB
SETATTR BB,NAME=MOTHER,VALUE=MM
* assign a given MM as the mother

Setting the "MOTHER" attribute will result in a number of mergers. Pic.5a shows the net before this attribute is set (a "MOTHER" arc will be drawn from BB to MM). The nodes to be merged are connected with broken lines; pic.5b shows the state of the net when all merging is completed.

Repeated fetching of the same module will result in adding a new node with properties similar to those of the head node of the module. One may think that a module kept in the library represents a generic notion (a class) and head nodes of the copies represent instances of the class; making a new copy corresponds to introducing a new instance. This method of representing the relationship between an object and a generic notion (between the individual and the general) is preferrable to a formalistic indication by means of an arc named "kind", because in this method including an object in a class immediately results in new information and new connections (as in the last example). Treating the name of a library module as the name of a generic notion one can view the structure of the module as a representation of the content (intension) of the notion; its extend (extension) is not considered here.

A similar facility for modules is available in SIMULA where modules are named classes and there is an operation to make a new object of the given class.

This system allows not only to introduce a new object of a given class but also to ascribe a class to an existing node, i.e., to state that an object belongs to a certain class. This action consists basically in fetching a new copy of the module representing the class and merging the given node with the head node of the copy. But actually ascription of a class to an existing node does not amount to these actions but is rather a separate primitive of this system. One of the specific traits of this primitive is a special method used for resolving conflicts between attributes copied from the library and identically named original attributes of the nodes: under equal conditions the preference belongs to original attributes, i.e., a particular property of a particular object can cancel the corresponding property of the general notion, ascribed to the object.

In common, non-mathematical thinking it is just what we usually do. One of the properties of the "room" in general is presence of windows, while we accept that some particular room (say, a cinema room) may lack them. Note that in this system this is achieved without using fuzzy sets and similar ideas. The need in fuzzy sets arises when we want to solve the question whether a thing is, e.g., a room once and forever, without referring to our current activities (in this case, indeed, no clear-cut answer is possible). The system presented here reflects a different approach: in some circumstances one decides to include some object in a certain class and to act correspondingly (and possibly fail if the decision was unwise).

The system allows to represent not only membership of an individual object in a class but also inclusion of one class X in another class Y. To do it, the head node of the module for X is provided with a special reference to Y, that instructs the system at fetching a copy of X to ascribe to its head node the class Y, i.e., to attach to it a copy of the module for Y. Attribute conflicts between X and Y are resolved according to the same rules, i.e., attributes from the module X (defining the smaller class) take precedence over those from Y. This treatment of class inclusion is known in SIMULA that supports concatenation of classes and even assigning values specified by the smaller class to virtual attributes of the larger class.

In the definition of a module such a reference to another module that should be ascribed to a node at the time of fetching the first module may be placed not only on the head node. Any node in a module may have any number of such references to other modules, and copies of all of those modules will be added to this node at the time of fetching. (SIMULA does not have such facility but ADA can do a similar thing at using packages.) The process of adding new modules at fetching can cause an infinite loop; e.g., if one builds a module for "person" with attributes for "father" and "mother" with values both having references to the same "person" module (which represents the statements that any person's father is a person and any person's mother is a person) fetching of such a module will never stop because of indefinite growth of the tree of ancestors (pic.6, a-c). In the existing implementation such a module can be written but an attempt to fetch it will result in abnormal termination for memory overflow. However in some cases the implementation prevents infinite loops; it remembers the names of previously fetched modules and does not add a module to a node that is already a copy of the head node of the same module (or has been merged with such a copy). Cases are also known when addition of new modules did not result in a loop but increased heavily storage consumption. There is an idea to modify the implementation so that adding new modules to a node would be delayed until the first access to that node.

The operation of module fetching, as well as ascription to an existing node, involves (apart from copying) calling certain procedures. It is here that standard names for opening and closing functions (mentioned in #4) are used. The opening procedure (if any) is called by the system at fetch time, a call of the closing function is scheduled for the time of completion of the whole run of the system. When a module is added to an existing node, first the head node is merged with the given node (which may result in replacement of some attributes), and then the opening function is called.

The attributes defining the procedures for opening and closing might have been changed between the moment of copying and the moment of calling, whereas it is desirable that the procedures called be exactly those originally specified, and be called in a specific order; therefore the following sequence of actions is used:

the values of the attributes defining the opening and closing procedures are taken immediately after copying (before any mergers), and so remembered;

opening modules added to the module fetched is done before opening the latter but after all mergers;

closing modules at the completion of the run of the system is performed in the reverse order as compared to the order of opening.

In the implementation some modules represent unique system resources (e.g., some files). Such modules are defined as atoms. At the first access to such an atom the system automatically assigns to it all the attributes from the module and performs all the initializing actions. any subsequent access to the atom of the same name returns the same atom. Thus opening a file (in OS sense) included in the opening procedure of the module is done only once and automatically, and all accesses to the module refer to the same system control blocks for the file; closing the file is done automatically too (at the time of closing the module) when the system run is completed.

The library of modules is implemented as OS library of load modules. The same library contains separate procedures. It is convenient to specify this library as a concatenation of the general library of the system and the library of the current problem area. The names of procedures and modules referred to earlier are just names of the corresponding library members. A module, as well as a procedure, is added to the library by assembling and subsequent link editing an assembly language source text. As an example we list the source for the mentioned "person" module (which actually cannot be used).
PERSON DEFNET (FATHER,F),(MOTHER,M)
* definition of the head node and its attributes
F DEFNODE MODEL=PERSON
* a node definition, no attributes given, a reference is
* made to the ascribed module (the same as this module)
M DEFNODE MODEL=PERSON
DEFATOMS FATHER,MOTHER
* definition of the atoms used
ENDNET
* end of the net definition, procedures may follow

Procedures included in module definition may access the nodes of the module immediately. In each copy of the module the procedures will access the nodes in this copy, thus the nodes are part of the own context of such a procedure.

We see that in this system the net and the library have fully distinct functions. The net contains objects and facts of the current situation, while the library contains permanent knowledge of the system, including relationships between object classes and procedures to handle various classes of objects. Modification or enhancement of the collection of permanent knowledge in the course of handling particular objects is not represented in this system.