#9. Implementation. An experimental version of this system has been implemented on ES computers under OS ES with a heavy use of facilities provided by the operating system.
A vertex of the net is represented with one fullword with the high-order byte containing the type of the vertex and the three low-order bytes containing the address of the information block of this vertex (for an integer the three bytes contain its binary representation, for a procedure, its entry point).
For each atom, node, or arc a standard information block is built, four words long. The block for an arc contains the address of the block for the next arc issuing from the same node, the name of the arc (represented as specified above), its status and the vertex where it ends. In the block for an atom or a node one word is reserved for the address of the first arc issuing from this atom or node. The character representation of the name of an atom is kept only in its information block. Node merging is effected by storing in the information block of one node the pointer to such block of the other node and transferring all outgoing arcs from the first node to the second. All operations referring to a node first trace the chain of such references and do actual work only with the block where the chain ends.
Module fetching is based on the system LOAD macro with subsequent modification of the loaded data. In order to avoid, at repeated fetching, getting from the operating system the old copy of the module, the LOAD operation has been split into BLDL and LOAD DE, between which the library name of the module in the DE block is replaced by a unique name.
A procedure is called by means of usual LINK or CALL macros. At entry it receives in GPR 13 the address of the system save area, the same for all procedures. Next to this area common system data are stored, consisting mainly of entry point addresses of subroutines implementing system primitives (there are about 25 such subroutines); other system data are stored in the bodies of the subroutines. The assembly language expansions of macros constituting a procedure consist of loading a subroutine address (by a fixed displacement from register 13), a branch and link to the subroutine, and sometimes also parameters (e.g., atom names). The atom name in such an expansion is replaced by its internal representation at the first call to the subroutine, so any subsequent calls can skip the search for the atom information block.
A procedure may include ordinary assembly language instructions provided they do not violate register conventions.
Any procedure starts with a call to a data allocation subrooutine, the data area size being passed as a parameter (it is always known in advance). Thus recursive calls are supported. There is a stack of data areas of procedures in progress, with the current procedure data area on the top. When the procedure is completed the area is popped off the stack and freed.
Restoration of data at failures is supported by another stack where all changes are entered that have to be reversed on restoration. The changes are entered as addresses of words modified and their previous contents rather than in terms of nodes and attributes; this allows faster restoration. For a procedure call having provisions for a failure, a return control block is built in the data area of the caller, containing current value of restoration stack top pointer and a pointer to the external return control block, if any. On successful completion of the call the top of the restoration stack remains where it is if there is at least one remaining (external) return control block.
Recursive calls and restoration are extensively utilized by system support routines.
The storage for new atoms, nodes, and attributes, for the stacks for calling and restoration is taken from the operating system in portions of 2K and is never freed until the completion of the task. The modules loaded are also freed only at completion. Storage reusing is possible only in stacks. Garbage collection is not implemented. However the system is viable and does not require very large amounts of storage (usually about 50K, in some cases up to 200K). This is due to the fact that it is not designed for doing long jobs or solving problems involving extensive searching. If a long computation is needed, the appropriate way of using this system is to generate or compile programs that can work without this system or with calling this system on rare occasions.
I / O is done by means of special modules used in package mode (see #4). There is a scanner module that can be attached to the main node of any input module to provide additional functions of reading integers, atoms, strings, and other operations. The original module has to support only the function to read one line. Output to the standard file (SYSPRINT) is supported by special macros with some control of format. The same macros allow to specify as an extra parameter a different output file, defined as an output package. Input and output packages can be combined in a single node, and there are modules producing such packages at fetching. A similar module is planned for access to a database which will have the form of another association net [6].
Debugging aids at this stage include a readable dump of the procedure stack and the current state of the net and an abort primitive causing a similar dump and a message. An abort can be initiated also by system support routines (e.g., because of a wrong vertex type). There is no dump of the procedure queue or restoration stack (the latter could be used as tracing record). Some analysis is done for abnormal end initiated by the operating system. There is a special assembly mode for procedures enabling a trace of entries, exits, and failures.
The kernel load module of the system, including all support routines, has the size of 11K. The macro library has about 1000 lines of code, the source assembly language code is about 4000 lines.
A high level language is being developed for procedures and modules.