ENUMERATED TYPES


1. OVERVIEW

An enumerated type is a user defined discrete scaler type where the possible values for the type are itemised. Ada example declaration:

type DAYS is (MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY, SUNDAY);
NEWDAY: DAYS := WEDNESDAY;

Here we have created an "enumerated" type DAYS and an instance, NEWDAY of that type. Note that the values in a enumerated type are "ordered" so that the value listed first is least and the value listed last is greatest. Conceptually at least, each value for an enumeration also has an ordinal value. This allows comparison of enumerated type values using operators such as < (less than) and > (greater than).

2. ATTRIBUTES FOR ENUMERATED TYPES

Ada provides a number of attributes for enumerations:

FirstGives first value of the enumeration
LastGives last value of the enumeration
pred(X)Gives the predecessor of the enumerated value X
succ(X)Gives the successor of the enumerated value X

Note that the value used in conjunction with the pred and succ attributes must not be the first or last values respectively. Example of the application of enumeration attributes:

with TEXT_IO ;
use TEXT_IO ;

procedure ENUMERATION_ATTRIBUTES is
        type DAYS is (MONDAY, TUESDAY, WEDNESDAY,
                THURSDAY, FRIDAY, SATURDAY, SUNDAY);
        package DAYS_INOUT is new ENUMERATION_IO(DAYS);
        use DAYS_INOUT;
        NEWDAY: DAYS;

begin
        PUT("DAYS'FIRST:= ");
        PUT(DAYS'FIRST);
        NEW_LINE;
        PUT("DAYS'LAST:= ");
        PUT(DAYS'LAST);
        NEW_LINE;
        GET(NEWDAY);
        PUT("NEWDAY:= ");
        PUT(NEWDAY);
        NEW_LINE;
        PUT("DAYS'PRED(NEWDAY):= ");
        PUT(DAYS'PRED(NEWDAY));
        NEW_LINE;
        PUT("DAYS'SUCC(NEWDAY):= ");
        PUT(DAYS'SUCC(NEWDAY));
        NEW_LINE;
        if (NEWDAY < THURSDAY) then
                PUT("if NEWDAY < THURSDAY, NEWDAY:= ");
                PUT("MONDAY, TUESDAY or WEDNESDAY");
                NEW_LINE;
        end if;
end ENUMERATION_ATTRIBUTES;

Note how input/output for the enumerated type has been achieved in the above example.


3. FURTHER EXAMPLES OF ENUMERATED TYPES

In an earlier example progarm a simple calculator applicvation was produced. This allowed users to input a simple arithmetic expression of the form:

<OPERAND> <OPERATOR> <OPERAND>

Where <OPERAND> is an integer of some kind and <OPERATOR> is one of the operators `+', `-', `*' or `/'. The top level procedure for the implementation commenced as follows:

procedure CALCULATOR is
    subtype OPERAND_T is INTEGER range -14654..14654;
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    OPERAND_1, OPERAND_2 : OPERAND_T;
    OPERATOR             : CHARACTER;

and so on. An alternative to the above might be:

procedure CALCULATOR is
    type OPERATOR_T is ('+', '-', '*', '/');
    subtype OPERAND_T is INTEGER range -14654..14654;
    package OPERATOR_INOUT is new ENUMERATION_IO(OPERAND_T);
    use OPERATOR_INOUT;
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    OPERAND_1, OPERAND_2 : OPERAND_T;
    OPERATOR             : OPERATOR_T;

Here we have defined the data item OPERATOR as being of type OPERATOR_T which in turn is defined as an enumerated type. This alternative implementation offers the advantage that values for the OPERATOR data item are checked automatically.


3.1. Predefined Enumerated Types

A well known enumerated types (although not often recognised as such) is the Boolean type. In Ada this would be specified as follows:

type BOOLEAN is (FALSE, TRUE);

It is also possible to consider any discrete type (e.g. integer, character) to be an enumerated type.


4. EXAMPLE PROBLEM TEMPORAL REASONING


4.1. Requirements

Develop a temporal reasoning system which when given (1) the temporal relationship that exists between tow points A and B and (2) the temporal relationship that exists between the point B and a further point C, determines the temporal relationship that exists between the points A and C.

Note that there are only three temporal relations that can exist between any two points located along a time line: "before", "equals" and "after". Thus there are three relations that can link the points A and B, and three relations that can link the points B and C.

To determine the relation between A and C we can use a technique known as a transitivity table. This comprises a table with the possible relations between A and B represented by the horizontal axis, and the possible relations between B and C represented by the vertical axis. At the intersections are given the relations that must exist between A and C given particular coordinate relations. Thus:

Relation between A and B
Relation between B and CBeforeEqualsAfter
BeforeBeforeBeforeBefore, Equals or After
EqualsBeforeEqualsAfter
AfterBefore, Equals or AfterAfterAfter

4.2. Design

A top-down analysis of the proposed problem is given below.

TOP DOWN ANALYSIS

We will implement this using four procedures/functions:

  1. TEMPORAL_REASONING (Top level procedure): Define enumerated type for permitted relations. Read in relation AB and relation BC. Call RELATION_AC function.
    NAMEUSAGETYPERANGE
    RELATION_ABInput variableRELATION (Enumerated type)BEFORE, EQUALS, AFTER
    RELATION_BCInput variableRELATION (Enumerated type)BEFORE, EQUALS, AFTER
  2. RELATION_AC (Level 2 procedure): Case statement for relation AB. Calls to BEFORE_AB, AFTER_AB and EQUALS_AB as appropriate.
    NAMEUSAGETYPERANGE
    REL_ABFormal parameterRELATION (Enumerated type)BEFORE, EQUALS, AFTER
    REL_BCFormal parameterRELATION (Enumerated type)BEFORE, EQUALS, AFTER
  3. BEFORE_AB (Level 3 procedure): Case statement for relation BC. Appropriate output for relation AC.
    NAMEUSAGETYPERANGE
    REL_BCFormal parameterRELATION (Enumerated type)BEFORE, EQUALS, AFTER
  4. EQUALS_AB (Level 3 procedure): Case statement for relation BC. Appropriate output for relation AC.
    NAMEUSAGETYPERANGE
    REL_BCFormal parameterRELATION (Enumerated type)BEFORE, EQUALS, AFTER
  5. AFTER_AB (Level 3 procedure): Case statement for relation BC. Appropriate output f or relation AC.
    NAMEUSAGETYPERANGE
    REL_BCFormal parameterRELATION (Enumerated type)BEFORE, EQUALS, AFTER

Complete Nassi-Schneiderman charts for the above are given below:

NASSI_SCHNEIDERMAN CHART

NASSI_SCHNEIDERMAN CHART

A Data Flow Diagram indicating the broad flow of control through the above is given below.

FLOW CHART

4.3. Implementation

-- TEMPORAL REASONING
-- 1 October 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool

with TEXT_IO;
use TEXT_IO;
procedure TEMPORAL_REASONING is
    type RELATION is (before, equals, after);
    package RELATION_INOUT is new ENUMERATION_IO(RELATION);
    use RELATION_INOUT;
    RELATION_AB, RELATION_BC : RELATION;

    -----------------------------------------------------------------------
    -- Identify horizontal element in transitivity table
    procedure RELATION_AC(REL_AB, REL_BC : RELATION) is
        -------------------------------------------------------------------
        -- BEFORE AB
        procedure BEFORE_AB(REL_BC : RELATION) is
        begin
            case REL_BC is
                when before | equals =>
                    PUT_LINE("A before C");
                when after =>
                    PUT_LINE("A before, equals or after C");
            end case;
        end BEFORE_AB;
        -------------------------------------------------------------------
        -- EQUALS AB
        procedure EQUALS_AB(REL_BC : RELATION) is
        begin
            case REL_BC is
                when before =>
                    PUT_LINE("A before C");
                when equals =>
                    PUT_LINE("A equals C");
                when after =>
                    PUT_LINE("A after C");
            end case;
        end EQUALS_AB;
        -------------------------------------------------------------------
        -- AFTER AB
        procedure AFTER_AB(REL_BC : RELATION) is
        begin
            case REL_BC is
                when before =>
                    PUT_LINE("A before, equals or after C");
                when others =>
                    PUT_LINE("A after C");
            end case;
        end AFTER_AB;
        -------------------------------------------------------------------

    begin
        case RELATION_AB is
            when before =>
                BEFORE_AB(REL_BC);
            when equals =>
                EQUALS_AB(REL_BC);
            when after =>
                AFTER_AB(REL_BC);
        end case;
    end RELATION_AC;
    -----------------------------------------------------------------------

begin
-- Input data
    PUT_LINE("Input relation A and B (before, equals or after)");
    GET(RELATION_AB);
    PUT_LINE("Input relation B and C (before, equals or after)");
    GET(RELATION_BC);
-- Determine relation linking points A and C
    RELATION_AC(RELATION_AB,RELATION_BC);
    NEW_LINE;
end TEMPORAL_REASONING;

4.4. Testing

TEST CASEEXPECTED RESULT
RELATION_ABRELATION_BCOUTPUT
beforebeforebefore
beforeequalsbefore
beforeafterbefore, equals or after
equalsbeforebefore
equalsequalsequals
equalsafterafter
afterbeforebefore, equals or after
afterequalsafter
afterafterafter
between*DATA_ERROR
beforebetweenDATA_ERROR

The simplest way to test the above code is to test every combination of input. There are only nine of these as shown in the table to then right. We should also test an input for each relation which is not included in the enumeration. These tests will ensure that all paths through the system are followed.


Example Problem Temporal Reasoning.




Created and maintained by Frans Coenen. Last updated 11 October 1999