====================
Enumeration Types
====================

-------------------
Enumeration Types
-------------------

**Syntax**

.. container:: source_include 030_scalar_types/syntax.bnf :start-after:enumeration_types_begin :end-before:enumeration_types_end :code:bnf

* Enumeration of **logical** values

    - Integer value is an implementation detail

* Literals

   - Distinct, ordered
   - Can be in **multiple** enumerations

**Examples**

.. code:: Ada

   type Colors is (Red, Orange, Yellow, Green, Blue, Violet);
   type Stop_Light is (Red, Yellow, Green);
   ...
   -- Red both a member of Colors and Stop_Light
   Shade : Colors := Red;
   Light : Stop_Light := Red;

-----------------------------
Enumeration Type Operations
-----------------------------

* Assignment, relationals
* **Not** numeric quantities

.. code:: Ada

   type Directions is (North, South, East, West);
   type Days is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
   Heading : Directions;
   Today, Tomorrow : Days;
   ...
   Today := Mon;
   Today := North; -- compile error
   Heading := South;
   Heading := East + 1; -- compile error
   if Today < Tomorrow then ...

-----------------------------
Enumeration Type Attributes
-----------------------------

.. code:: Ada

   type Days is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);

* :ada:`T'Pred (Input)`

  - Predecessor of specified value
  - :ada:`Days'Pred (Tue)` |rightarrow| :ada:`Mon`
   
* :ada:`T'Succ (Input)`

  - Successor of specified value
  - :ada:`Days'Succ (Tue)` |rightarrow| :ada:`Wed`

* Additional information

  - Going past the end (:ada:`Days'Pred(Mon)` or :ada:`Days'Succ(Sun)`) raises :ada:`Constraint_Error`
  - These attributes are available for all scalars, but not particularly useful for numerics

---------------
Character Types
---------------

* Literals

   - Enclosed in single quotes eg. :ada:`'A'`
   - Case-sensitive

* **Special-case** of enumerated type

   - At least one character enumeral

* System-defined :ada:`Character`
* Can be user-defined

  .. code:: Ada

     type EBCDIC is (nul, ..., 'a' , ..., 'A', ..., del);
     Control : EBCDIC := 'A';
     Nullo : EBCDIC := nul;

-------------------------------
Language-Defined Type Boolean
-------------------------------

* Enumeration

  .. code:: Ada

     type Boolean is (False, True);

* Supports assignment, relational operators, attributes

  .. code:: Ada

     A : Boolean;
     Counter : Integer;
     ...
     A := (Counter = 22);

* Logical operators :ada:`and`, :ada:`or`, :ada:`xor`, :ada:`not`

  .. code:: Ada

     A := B or (not C); -- For A, B, C boolean

---------------------------------------
Boolean Operators' Operand Evaluation
---------------------------------------

* Evaluation order **not specified**
* May be needed

  - Checking value **before** operation
  - Dereferencing null pointers
  - Division by zero

.. code:: Ada

  if Divisor /= 0 and K / Divisor = Max then ... -- Problem!

-----------------------------
Short-Circuit Control Forms
-----------------------------

* **Short-circuit** |rightarrow| **fixed** evaluation order
* Left-to-right
* Right only evaluated **if necessary**

   - :ada:`and then`: if left is :ada:`False`, skip right

     .. code:: Ada

        Divisor /= 0 and then K / Divisor = Max

   - :ada:`or else`: if left is :ada:`True`, skip right

     .. code:: Ada

        Divisor = 0 or else K / Divisor = Max

------
Quiz
------

.. code:: Ada

   type Enum_T is (Able, Baker, Charlie);

Which statement(s) is (are) legal?

A. :answermono:`V1 :  Enum_T := Enum_T'Value ("Able");`
B. :answermono:`V2 :  Enum_T := Enum_T'Value ("BAKER");`
C. :answermono:`V3 :  Enum_T := Enum_T'Value (" charlie ");`
D. ``V4 : Enum_T := Enum_T'Value ("Able Baker Charlie");``

.. container:: animate

   Explanations

   A. Legal - String matches an enumeral
   B. Legal - conversion is case-insensitive
   C. Legal - leading/trailing whitespace is ignored
   D. :ada:`Value` tries to convert entire string, which will fail at run-time

