[Ada Information Clearinghouse]
Ada '83 Rationale, Sec 15.5: Enumeration Types with Noncontiguous Representations

"Rationale for the Design of the
Ada® Programming Language"

[Ada '83 Rationale, HTML Version]

Copyright ©1986 owned by the United States Government. All rights reserved.
Direct inquiries to the Ada Information Clearinghouse at adainfo@sw-eng.falls-church.va.us.

CHAPTER 15: Representation Clauses and Machine Dependences

15.5 Enumeration Types with Noncontiguous Representations

The specified internal codes of an enumeration type need not have contiguous values. This degree of generality is required if character types are to be represented by enumeration types, since many character sets have noncontiguous internal values.

We next discuss the implications of noncontiguous representations on assignment and comparison, indexing and case selection, and finally on iteration.

In this section...

15.5.1 Assignment and Comparison with Noncontiguous Enumeration Types
15.5.2 Indexing and Case Statements with Noncontiguous Enumeration Types
15.5.3 Iteration Over Noncontiguous Enumeration Types
15.5.4 Character Types


15.5.1 Assignment and Comparison with Noncontiguous Enumeration Types

An assignment only results in moving a value from one location to another, and thus is not influenced by the noncontiguity of a representation. Similarly, noncontiguity has no impact on comparison.


15.5.2 Indexing and Case Statements with Noncontiguous Enumeration Types

The simplest way to treat an array indexed by an enumeration type that has a noncontiguous representation is to implement it as a normal array, but leaving holes (that is, unused positions) in the storage used. No conversion is then needed between the internal code and the actual index to storage, since they have the same value. In a similar way, the internal jump table used for a case statement could have holes.

Note that no problem arises when such arrays are passed as parameters to subprograms since the index type is part of the array type and the same mapping will be used inside and outside the subprogram.

The user should be aware of the hidden storage costs involved: these costs are certainly preferable to prohibiting the use of types with noncontiguous representations for indexing and in case statements. If we consider character sets, for instance, the proportion of holes remains at an acceptable level.


15.5.3 Iteration Over Noncontiguous Enumeration Types

We are faced with a more severe problem when a loop parameter ranges over the values of a noncontiguous enumeration type: simply incrementing the value of the loop parameter by a constant at each iteration will not work! To keep the same underlying mechanism, the compiler may use a characteristic vector, that provides information on holes. For every such loop, the compiler will include code to interrogate the characteristic vector.

This mechanism is illustrated by the following example. Consider the type MIX_CODE, for which a noncontiguous representation has been specified.

type MIX_CODE is (ADD, SUB, MUL, LDA, STA, STZ);
for MIX_CODE use
  (ADD =>  1, SUB =>  2, MUL = > 3, LDA =>  8, STA =>  24, STZ => 33);

A loop statement that iterates over the values of the MIX_CODE type can be written as follows:

for N in MIX_CODE loop
  DISPLAY(N);
end loop;

The compiler could produce object code equivalent to the following text (apart from typing rules):

PRESENT :  constant array (1 .. 33) of BOOLEAN :=
            (1 | 2 | 3 | 8 | 24 | 33 =>  TRUE,  others =>  FALSE);

for J in PRESENT'RANGE loop
  if PRESENT(J) then
    DISPLAY(J);
  end if;
end loop;

As illustrated above, the compilation involves a characteristic vector (PRESENT) which is used to generate the integer values corresponding to the enumeration type MIX_CODE. Thus we see that iterating over such types is possible, but involves extra cost.

Another technique is to use a representation vector that maps the ordinals into the enumeration values:

REPRESENTATION  :     constant   array  (0  ..  5)  of  INTEGER  := (1,2,3,8,24,33);
for J in REPRESENTATION'RANGE loop
  DISPLAY(REPRESENTATION(J));
end loop;

Similar techniques are used to implement 'SUCC, 'PRED, 'POS and 'VAL.


15.5.4 Character Types

Character types are a typical example of enumeration types with not necessarily contiguous representations. The predefined character type CHARACTER that denotes the full ASCII character set of 128 characters is contiguous, but the same is not true for other widely used character sets such as EBCDIC. Such character sets will generally be defined in library modules, which will include both the character type declaration and the associated representation specification. It may be convenient to provide such a definition in two steps. For example:

type CHAR is (enumeration of all EBCDIC characters);

type EBCDIC is new CHAR; -- same characters as CHAR

for EBCDIC use (codes corresponding to EBCDIC characters);

A user to whom the internal code is relevant (perhaps because he is performing input-output) will declare objects of type EBCDIC. For other uses, especially if such characters are to be used as indices, in case statements and in iterations, the user might prefer to use the type CHAR. Since no representation specification is given for this type, the translator will adopt a default representation that is convenient for indexing and iteration. Explicit conversion between the two types can be performed.

Note however that CHAR and EBCDIC will have their values in the same order, so the user cannot be relieved of all the problems associated with this wretched data type.


NEXTPREVIOUSUPTOCINDEX
Address any questions or comments to adainfo@sw-eng.falls-church.va.us.