ada

Why Ada attribute 'value in this snippet doesn't raise Data_Error but Constraint_Error instead?


The snippet use a My_Color'Value to convert from String to My_Color and it just raise the Constraint_Error but not the Data_Error as supposed it. The first block of code works if you enter a correct color, but if enter a wrong color or random character is when the Constraint_Error is raised.


with Ada.Text_IO;
procedure test_get_enum_loop is
   type My_Color is (red, yellow, green);

   package Color_IO is new Ada.Text_IO.Enumeration_IO (My_Color);
   
   use Color_IO;
   use Ada.Text_IO;

   Color : My_Color;
begin
   -- Loop with 'value attribute
   loop
      begin
         Put ("Enter a color: ");
         Color := My_Color'Value(Get_Line);
         Put_Line ("The color is " & Color'Image);
         exit;
      exception
         when Data_Error => 
            Put_Line ("Error, you did not enter a Color");
         when Constraint_Error =>
            Put_Line ("Error, Constraint_Error");
      end;     
   end loop; 

This code it is the continuation of above and it work as intended:

   New_Line;
   -- Loop with Get
   loop
      declare
         Color : My_Color;
         Last  : Natural;
      begin
         Put ("Enter a color: ");
         Get (Get_Line, Color, Last);
         Put_Line ("The color is " & Color'Image);
         exit;
      exception
         when Data_Error => 
            Put_Line ("Error, you did not enter a Color");
         when Constraint_Error =>
            Put_Line ("Error, Constraint_Error");
         when End_Error =>
            Put_Line ("You entered Nothing, try again");
      end;     
   end loop;     
end test_get_enum_loop;

I have gotten the program to work as I wanted using the 'valid' attribute to verify that when you enter incorrect information or nothing the appropriate exception is raised

with Ada.Text_IO;
procedure test_get_enum_loop is
   type My_Color is (red, yellow, green);

   package Color_IO is new Ada.Text_IO.Enumeration_IO (My_Color);
   
   use Color_IO;
   use Ada.Text_IO;

   Color : My_Color;
begin
   -- Loop with 'value attribute
   loop
      begin
         Put ("Enter a color: ");
         -- Color := nothing;
         declare
            Tmp : String := Get_Line;
         begin
            if Tmp = "" then
               raise End_Error;
            else   
               Color := My_Color'Value(Tmp);
            end if;
         end;    
         Put_Line ("The color is " & Color'Image);
         exit;
      exception
         when End_Error =>
            New_Line;
            Put_Line ("Error, you entered nothing, try again");
            New_Line;
         when Constraint_Error =>
            New_Line;
            Put_Line ("Error, you did not enter a Color, try again");
            New_Line;
      end;     
   end loop; 
end test_get_enum_loop;

Greetings from curiousautistic


Solution

  • The snippet use a My_Color'Value to convert from String to My_Color and it just raise the Constraint_Error but not the Data_Error as supposed it.

    ARM 3.5 (51-55) defines 'Value:

    S'Value     S'Value denotes a function with the following specification:

    function S'Value(Arg : String) return S'Base

    This function returns a value given an image of the value as a String, ignoring any leading or trailing spaces.

    {AI95-00285-01} {AI05-0264-1} For the evaluation of a call on S'Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Image for a value of the type), the result is the corresponding enumeration value; otherwise, Constraint_Error is raised. For a numeric subtype S, the evaluation of a call on S'Value with Arg of type String is equivalent to a call on S'Wide_Wide_Value for a corresponding Arg of type Wide_Wide_String.

    In other words, 'Value is not supposed to raise Data_Error; it is defined to raise Constraint_Error.