[Up] [Previous]

Appendix II: Implementation Notes

Mutable Variables

EXALT allows untyped variables, called MUTABLE, which can be assigned values of any type. This is true of several other languages, APL being perhaps the one best known among people interested in conventional languages like EXALT.

However, EXALT also has static typed variables. The simultaneous existence of both kinds of variables creates potential problems for implementors.

A mutable variable can be thought of as being implemented as follows: each mutable variable is assigned static storage for two data items, its type and its address, and the address points into a large pool of storage to the value of that variable. When an assignment to a mutable value is made, the old value is abandoned, and empty pool storage is used to hold the new value. Assignment of one variable to another can be done just by moving pointers.

This simple model will fail in EXALT because of the existence of non-mutable variables if efficiency is to be maintained for simple constructs, and at any time for some specialized ones provided by EXALT.

Assignment, from an expression or a non-mutable variable, to a mutable variable of a value having the same type and dimension as that variable's present contents, should (unless temporary storage already contains the full new value from an expression) be done without changing the pointer of a mutable variable. This will reduce the frequency of garbage collection, a significant source of overhead.

To do this safely, the static storage associated with each MUTABLE variable must contain a flag, to indicate whether or not its present contents could also be referenced by other MUTABLE variables due to a variable to variable assignment, since pure pointer assignment is too useful to give up.

Since no flag-checking is done with regards to non-mutable variables, assignment from an ordinary variable to a mutable variable is not to cause the mutable variable's pointer to point into ordinary variable storage; copying, whether into the variable itself, or into fresh pool storage, is always needed.

However, it is permissible to explicitly cause, using the _MQ function, the pointer of a mutable variable to point into regular variable storage. This is done to induce what would normally be undesirable side effects of this situation. The FREEZE statement is often used after the use of the _MQ function, so that the pointer and type of the mutable variable cannot be changed until it is named in an UNFREEZE statement.

It is also legitimate for an implementor to do this where a non-mutable variable is passed as a parameter to a function requiring a mutable argument; on exit from the function, a copy of data to the original argument is performed if that variable's address has changed during execution. Not only is it legitimate, but highly recommended, as large arrays may well be passed to such functions and/or subroutines, as the use of mutable type is the only reasonable means provided by EXALT for the passing of type and dimension information during execution.

This means that the dynamic-storage value of a mutable variable must have the same form as that of a static variable of the same type, or, at least, be capable of having that form. Since the dimensions, as well as other structural details relating to type, of a variable may require a variable-length field to hold them, this means that that information must not be part of the value area; thus, a value pointer and a dimension/structure pointer are both required in a mutable variable's descriptor. One permissible difference in form is to allow a mutable variable to be stored with its dimensions transposed, since normal storage can be indicated by the same method that allows transposition.

Alternatives

The meaning of an alternative as part of an IF statement is simple and obvious, as similar constructs exist in many other languages. Alternatives in the return-code section of a call, and arguments of type alternative to a subroutine are manifestations of the same construct.

Subroutine arguments of type SEQUENCE are required to return to the subroutine of which they are arguments, and branching out of them is not allowed.

Alternatives in an UPON statement, however, when they are in the form of sequences, may branch into the program in which the statement is found, but if they do not do so, fall-through is back to the point in the program where the exception ocurred. Therefore, an UPON statement must store return information in local storage specific to itself rather than allowing it to remain within a stack. As well, it must disconnect the EXALT subroutine call mechanism, in so far as it applies to programs called by the program in which the UPON statement was found, so that if a branch out is taken, any STOP or RETURN statements will execute normally based on the present location of execution.

The GOSUB and RETSUB statements create an additional level of complexity, which can be solved by isolating the GOSUB stacks of separate modules, which should be a requirement of any implementation for error safety in any case.


[Up] [Previous]