Ada '83 Rationale, Sec 15.3: Multiple Representations and Change of Representation

## CHAPTER 15: Representation Clauses and Machine Dependences

### 15.3 Multiple Representations and Change of Representation

When a program has to deal with objects that exist on an external medium, one is faced with the problem of multiple representations. For example, records may be stored in a packed form on a file; but a program may need faster access to the record components when the information is processed, and hence may require an unpacked form. This is a classic situation in which different representations for the same objects are wanted.

Although the details of the alternate representations are not part of the logical properties, we will show with the following example that the knowledge of the existence of alternate representations is, itself, a logical property.

### 15.3.1 A Canonical Example of Changes of Representation

Consider the problem of converting data from some external medium into a form ready to be output onto another external medium. Both data objects belong to the same enumeration type, but they have different representations, each of which is prescribed by the outside world. The following program fragment gives a hypothetical formulation (not following the Ada syntax) for the required procedure:

 ```procedure CONVERT is -- declarations of the logical properties: type DAY is (MON, TUE, WED, THU, FRI, SAT, SUN); X, Y : DAY; -- representation clauses (not in the Ada syntax): representation FORM_A of DAY is (MON => 0, TUE => 1, WED => 2, THU => 3, FRI => 4, SAT => 5, SUN => 6); representation FORM_B of DAY is (MON => 1, TUE => 2, WED => 3, THU => 4, FRI => 5, SAT => 6, SUN => 7); for X use representation FORM_A; for Y use representation FORM_B; -- end of representation clauses (in hypothetical syntax) begin ... Y := X; ... end CONVERT; ```

In trying to establish the correctness of the above procedure, one finds that the information contained in the logical declarations of X and Y does not suffice. It can only be concluded that X and Y are of type DAY. To complete the correctness proof (that conversion is properly effected) it is necessary to consider representation clauses, and hence to violate the separation principle mentioned earlier. We are thus led to the conclusion that any attempt to hide the existence of multiple representations at the logical level ultimately leads to a violation of the separation principle.

### 15.3.2 One Type - One Representation Principle

It is natural and desirable to use type as a carrier for representation. The approach adopted in Ada is to have a unique representation of each type and to select the representation explicitly by representation clauses. This results in a significant simplification, since the user does not have to think in terms of multiple representations for a single type.

If we need two different representations, two different types are therefore required, although these two types should have identical logical properties: the solution to this problem is to use derived types. For example, a type B can be derived from a type A by declaring

`    type B is new A;`

Since B derives its characteristics from A, both types have the same characteristics, for example the same components. However, they are distinct types and it is hence possible to specify different representations for A and for B. Change of representation can be achieved by explicit conversion between objects of types A and B since such conversions are defined for derived types. Derivation has the effect of creating a type with the same characteristics as another type, without rewriting its entire description (that would define a distinct type for which no conversions are possible).

#### Note:

The one type - one representation principle must be understood in terms of the knowledge that the user has from the existence (as opposed to the details) of a representation. It means that if a representation is explicitly specified for a type, then only one representation can be specified for this type. However, in cases where the representation is implicitly selected by the compiler, this does not preclude the use of different internal representations in different contexts - out of sight of the user.

### 15.3.3 Explicit Type Conversion and Change of Representation

The problem of change of representation is now straightforward: it can be expressed as an explicit type conversion between two derived types. As explained in Chapter 7, the type conversion appears syntactically as the call of a function with the name of the target type, for example:

`    Y :=  EXTERNAL_DAY(X);`

in the conversion problem presented earlier. The full solution may be properly expressed in Ada as follows:

 ```procedure CONVERT is -- declaration of the logical properties: type DAY is (MON, TUE, WED, THU, FRI, SAT, SUN); type EXTERNAL_DAY is new DAY; -- a derived type X : DAY := DAY'FIRST; Y : EXTERNAL_DAY; -- representation clauses for the two types: for DAY use (MON => 0, TUE => 1, WED => 2, THU => 3, FRI => 4, SAT => 5, SUN => 6); for EXTERNAL_DAY use (MON => 1, TUE => 2, WED => 3, THU => 4, FRI => 5, SAT => 6, SUN => 7); -- end of representation clauses begin ... Y := EXTERNAL_DAY(X); ... end CONVERT; ```

The correctness of this procedure can now be established without violation of the separation principle. First, we have to show that the program is correct given the definition of X and Y: Initially X contains a value of type DAY; the conversion EXTERNAL_DAY(X) is legal since the type EXTERNAL_DAY, is derived from the type DAY - it converts the value of X into a value of type EXTERNAL_DAY, which is finally assigned to Y. Secondly, it must be shown that the representations given for DAY and EXTERNAL_DAY are correct.

The same simple strategy would be used in the previously mentioned case of conversion of a record structure between a packed representation and an unpacked representation:

 ```type OBJECT is record -- declaration of the components of objects end record; type EXTERNAL_OBJECT is new OBJECT; -- a distinct type derived from OBJECT for EXTERNAL_OBJECT use record ... -- definition of the layout of record components end record; X : OBJECT; Y : EXTERNAL_OBJECT; ... X := OBJECT(Y); -- unpack ... Y := EXTERNAL_OBJECT(X); -- pack ```

### 15.3.4 Implementation of Representation Changes

Although they are limited to types that are conformable - having been declared to be logically equivalent - type conversions may be very costly in some cases. As an example consider a record type with variants:

 ```type V(D : BOOLEAN := TRUE) is record case D is when TRUE => I : INTEGER; when FALSE => R : REAL; end case; end record; type W is new V; for V use ... for W use ... X : V; Y : W; ... X := V(Y); ```

The implementation of the above assignment cannot be achieved as simply as for a normal record assignment. It must be done on a field by field basis, which is equivalent to the following program (apart from the restriction on assignment to the discriminant):

 ```X.D := Y.D; -- not legal Ada case Y.D is when TRUE => X.I := Y.I; when FALSE => X.R := Y.R; end case; ```

Producing such code is well within the capability of present compilation techniques. Nevertheless it is complex and can be somewhat costly on some computers (note that there might be variants within variants). Expressing changes of representation as explicit conversions warns the user of the potentially high cost of these operations.

NEXTPREVIOUSUPTOCINDEX