Enumeration Types, Boolean & Character
Define enumeration types, use their attributes ('First, 'Last, 'Pos, 'Val, 'Succ, 'Pred, 'Image, 'Value), iterate over them, understand overloaded enumeration literals, and work with the predefined Boolean and Character types and Ada.Characters.Handling.
An enumeration type lists every value it can take: 'type Color is (Red, Green, Blue);'. Unlike C, where enum constants are just integers, Ada enumeration values are their own type — you cannot add a Color to a number or compare it to a Weekday. Boolean and Character are themselves predefined enumeration types. This lesson shows how to declare, convert, print, parse and iterate over enumerations.
Declaring and Using Enumerations
The values are listed in order; that order defines comparison (Red < Green) and the position numbers returned by 'Pos (starting at 0). Enumeration types are discrete types, so they can be used as array indices, loop ranges and case selectors. A case statement over an enumeration must cover every value (or use 'when others'), so adding a new value later makes the compiler show every place that needs updating — a powerful maintenance aid.
Enumeration literals can be overloaded: Red can belong to both Color and Traffic_Light. The compiler resolves which one you mean from context; if context is ambiguous you qualify it: Color'(Red). Enumeration literals may also be character literals, which is exactly how Character is defined: type Character is (nul, ..., 'A', 'B', ...).
• type T is (A, B, C); — ordered, distinct, type-safe values. • Usable as array index, for-loop range, case selector. • case must cover all values → compiler flags missed cases when values are added. • Overloaded literals resolved by context or qualification T'(Lit).
Enumeration Attributes
T'First and T'Last give the first and last values; T'Pos (X) gives the position number; T'Val (N) converts a position back to a value; T'Succ (X) and T'Pred (X) give the next and previous values (raising Constraint_Error past the ends); T'Image (X) gives the upper-case name as a String; T'Value (S) parses a string (case-insensitive, surrounding spaces allowed) and raises Constraint_Error if it is not a valid literal. 'for X in T loop' iterates over every value.
• 'First / 'Last — bounds; 'Pos / 'Val — value ↔ position (0-based). • 'Succ / 'Pred — neighbours (error past the ends). • 'Image — upper-case text; 'Value — parse text (Constraint_Error on invalid input). • for X in T loop — iterate all values.
Boolean and Character
Boolean is 'type Boolean is (False, True);' with the logical operators and, or, xor, not and the short-circuit forms and then / or else. Conditions in if and while must be Boolean — an Integer is never implicitly a condition. Character is an enumeration of the 256 Latin-1 characters; Wide_Character and Wide_Wide_Character cover Unicode. Ada.Characters.Handling provides classification and conversion (Is_Letter, Is_Digit, Is_Upper, To_Upper, To_Lower), and Ada.Characters.Latin_1 names every character (LF, HT, NUL, ...).
• Boolean: (False, True); conditions must be Boolean. • Character: 256 Latin-1 values; Wide_ and Wide_Wide_Character for Unicode. • Ada.Characters.Handling: Is_Letter, Is_Digit, To_Upper, To_Lower... • Ada.Characters.Latin_1: named control characters (LF, CR, HT).
Code Examples
Shows every common attribute. Note Traffic_Light'Last is GREEN even though Color also has Green, and Color'Value ("blue") parses case-insensitively. Output: C = YELLOW C'Pos = 2 Succ (C) = GREEN Val (0) = RED First/Last = RED / BLUE Value = BLUE Light = GREEN RED ORANGE YELLOW GREEN BLUE Boolean'Pos (True) = 1
Character is an enumeration too: 'Pos gives the Latin-1 code, 'Val converts back, and a for loop can iterate over a character range. Output: Pos ('A') = 65 Val (97) = a To_Upper (g) = G Is_Digit ('7')= TRUE Is_Letter (?) = FALSE abcde if Count then -- Count: Integer...
if Count /= 0 then ...
Conditions must be Boolean; Ada never treats integers as true/false.
Next := Color'Succ (Color'Last);
Next := (if C = Color'Last then Color'First else Color'Succ (C));
'Succ of the last value raises Constraint_Error; wrap around explicitly if needed.
Put_Line (Color'Image (C)); -- expecting "Red" -- 'Image returns "RED"; convert case yourself if needed Put_Line (To_Lower (Color'Image (C)));
'Image returns the identifier in upper case.
For type Size is (Small, Medium, Large), what is Size'Pos (Large)? A. 3 B. 2 C. 1 D. Large B. 2 — positions start at 0.
What does Size'Value ("medium") return? A. Constraint_Error B. Medium C. 1 D. "MEDIUM" B. Medium — 'Value is case-insensitive.
What happens with Size'Succ (Large)? A. Small B. Large C. Constraint_Error D. Compile error
C. Constraint_Error — there is no successor of the last value.
Why is a full case statement over an enumeration useful for maintenance? A. It is faster B. Adding a new value causes compile errors where cases are missing C. It avoids exceptions D. It is required by style
B. The compiler flags every case statement that no longer covers all values.
Trace the enumeration example's output.
Real output: C = YELLOW C'Pos = 2 Succ (C) = GREEN Val (0) = RED First/Last = RED / BLUE Value = BLUE Light = GREEN RED ORANGE YELLOW GREEN BLUE Boolean'Pos (True) = 1
with Ada.Text_IO; use Ada.Text_IO;
procedure L6_Enum is
type Color is (Red, Orange, Yellow, Green, Blue);
type Traffic_Light is (Red, Amber, Green); -- Red/Green overloaded: fine in Ada
C : Color := Yellow;
T : constant Traffic_Light := Traffic_Light'Last;
begin
Put_Line ("C = " & Color'Image (C));
Put_Line ("C'Pos =" & Integer'Image (Color'Pos (C)));
Put_Line ("Succ (C) = " & Color'Image (Color'Succ (C)));
Put_Line ("Val (0) = " & Color'Image (Color'Val (0)));
Put_Line ("First/Last = " & Color'Image (Color'First) & " / " & Color'Image (Color'Last));
C := Color'Value ("blue"); -- parse text, case-insensitive
Put_Line ("Value = " & Color'Image (C));
Put_Line ("Light = " & Traffic_Light'Image (T));
for Shade in Color loop
Put (Color'Image (Shade) & " ");
end loop;
New_Line;
Put_Line ("Boolean'Pos (True) =" & Integer'Image (Boolean'Pos (True)));
end L6_Enum;with Ada.Text_IO; use Ada.Text_IO;
with Ada.Characters.Handling; use Ada.Characters.Handling;
procedure L6_Char is
Ch : constant Character := 'g';
begin
Put_Line ("Pos ('A') =" & Integer'Image (Character'Pos ('A')));
Put_Line ("Val (97) = " & Character'Val (97));
Put_Line ("To_Upper (g) = " & To_Upper (Ch));
Put_Line ("Is_Digit ('7')= " & Boolean'Image (Is_Digit ('7')));
Put_Line ("Is_Letter (?) = " & Boolean'Image (Is_Letter ('?')));
for C in Character range 'a' .. 'e' loop
Put (C);
end loop;
New_Line;
end L6_Char;