โŒ About FreshRSS

Normal view

There are new articles available, click to refresh the page.
Before yesterdayNews from the Ada programming language world

Is there a way to disable arithmetic operators on a specific type in Ada?

I would like to define HTML response status code numbers as a type but disallow arithmetic operators because it wouldn't make sense for them.

type Status_Code is range 100 .. 599;

function "+" (Left, Right : Status_Code) return Status_Code is
begin
      pragma Assert (1 = -1);
      return Left + Right;
end;

The code snippet above on GNAT will give an error saying assertion will fail on runtime, but that is false when I add two of the numbers together. Is there a way to force a compiler error or at least a warning when arithmetic attempted on a type like this?

A month in Ada

By: spqr
3 March 2023 at 17:50

The following simple Ada program prints a month in the form:

 SUN MON TUE WED THU FRI SAT
           1   2   3   4   5
   6   7   8   9  10  11  12
  13  14  15  16  17  18  19
  20  21  22  23  24  25  26
  27  28

It uses a simple process which asks the user the number of days in the month and the starting day of the week. The program demonstrates the overloading of packages in Ada, enumerations, types, subtypes, and output.

Here is the algorithm for displaying the month:

Output the heading with the names of the days of the week.
Output the initial blanks.
Set day = the first day input by the user.
loop date in 1 to number_of_days_in_the_month
   output(date)
   if (day = Saturday) then
      insert a new line
      day = Sunday
   else
      day = next day
   end
end loop
   

Here is the program written in Ada:

with text_IO; use text_io;

procedure month is

   subtype month_days is positive range 1..31;
   type week_days is (Sun,Mon,Tue,Wed,Thu,Fri,Sat);
   package positive_io is new integer_io(positive);
   use positive_io;
   package day_io is new enumeration_io(week_days);
   use day_io;
   answer: character;
   firstday: week_days;
   numberofdays: month_days;

   procedure get_number_of_days(nd: out month_days) is
   begin
      put("Enter the number of days in the month: ");
      new_line;
      get(nd);
      skip_line;
   end get_number_of_days;

   procedure get_first_day(fd: out week_days) is
   begin
      put("Enter the first day of the new month: ");
      put("e.g. Sun, Mon, etc.");
      new_line;
      get(fd);
      skip_line;
   end get_first_day;

   procedure display_month(nd: in month_days; fd: in week_days) is
      day: week_days := fd;
      four_blanks: constant string := "    ";
      width : constant integer := 4;
   begin
      for day in week_days loop
         put(' ');
         put(day);
      end loop;
      new_line;
      for blank_days in Mon..fd loop
         put(four_blanks);
      end loop;
      for date in 1..nd loop
         put(date,width);
         if day = Sat then
            day := Sun;
            new_line;
         else
            day := week_days'succ(day);
         end if;
      end loop;
      new_line;
   end display_month;

begin
   loop
      get_number_of_days(numberofdays);
      get_first_day(firstday);
      display_month(numberofdays,firstday);
      put("Do you wish to see another month? "); new_line;
      put("yes(y) or no(n): "); new_line;
      get(answer); skip_line;
      exit when answer = 'n' or answer = 'N';
   end loop;
end month;

You will notice on Line 9, the redefinition of the package enumeration_io to permit the output of the headings, and the input of the first day of the month in an intuitive manner. Also a subtype, month_days, is created on Line 5 of the program which helps ensure proper input by constraining the values allowed in month_days.

The program repeatedly prompts the user for information, and prints the associated month. Here is the programming running:

Enter the number of days in the month:
31
Enter the first day of the new month: e.g. Sun, Mon, etc.
Wed
 SUN MON TUE WED THU FRI SAT
               1   2   3   4
   5   6   7   8   9  10  11
  12  13  14  15  16  17  18
  19  20  21  22  23  24  25
  26  27  28  29  30  31
Do you wish to see another month?
yes(y) or no(n):
n

What happens if the number of days entered by the user is outside the constraints set? The program will raise a constraint error of the form:

raised CONSTRAINT_ERROR : month.adb:19 range check failed

But this can be fixed by modifying the user input routines. Here is how the procedure get_number_of_days() has been fixed.

   procedure get_number_of_days(nd: out month_days) is
      monthlen : month_days;
   begin
      loop
         begin
            put("Enter the number of days in the month: ");
            new_line;
            get(monthlen);
            skip_line;
            if monthlen in 28..31 then
               exit;
            else
               raise constraint_error;
            end if;
         exception
            when others =>
               skip_line;
               put("Bad input. Enter a value between 28-31.");
               new_line;
         end;
      end loop;
      nd := monthlen;
   end get_number_of_days;

On Lines 10-14 there is an if statement which determines if the input is valid. Input outside of the values 28-31 raises a constraint_error, but this time it is dealt with by the procedure on Lines 15-19 (instead of the system). If an exception is raised, then a message is output to the user, and in this case the loop iterates again. If the input is valid, the input loop is exited. This is a good example of how easy it is to deal with various exceptions in Ada. Here is a sample of the program running with invalid input:

Enter the number of days in the month:
42
Bad input. Enter a value between 28-31.
Enter the number of days in the month:

GNAT Studio ADA getting error "expected type "Standard.Integer"

In this Intro to Ada Course section about Arrays it shows that I can use a user defined type "Index" to index an array but when I try to index an array using a user defined type it says expected type "Standard.Integer". The reason why I'm asking this is because it explicitly states that you can use any discrete type to index an array.

procedure Cipher is
   type Byte is mod 2**8;
   type BufferArray is array ( 0 .. 15 ) of Byte;
   type Index is range 1 .. 16;
   Buffer: BufferArray := (0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
   buber: Byte := 255;
begin
   --  Insert code here.
   for I in Index loop
      Put( Byte'Image(Buffer(I)) ); --error shows up here
   end loop;
   null;
end Cipher;

Is it just possible that its an issue with this specific version of GNAT?

How do I declare a range within an array using an enumeration in Ada?

Say we have a type representing a box of a dozen donuts,

type Bakers_Dozen is range 1 to 13;  -- Indices from 1 to 6 are donuts

Each Donut has a unique value that's within Bakers_Dozen:

subtype Donut is Bakers_Dozen (Plain, Chocolate, Strawberry, Glazed, Blueberry, Cannabis);
for Donut use (Plain=>1, Chocolate=>2, Strawberry=>3, Glazed=>4, Blueberry=>5, Cannabis=>6);  

The intent is to refer to a Donut by either its name or value and ensure it only occupies range 1..6 of an array.

Unfortunately, my code results in an error message "incorrect constraint for this kind of type."

  PastriesBox[Plain].Message = "Plain Donut is boring but costs less";
  PastriesBox[Donut'Last].Message = "Please read contradictions and disclaimer inside box.";
  PastriesBox[12].Message = "A great tasting muffin with fresh goat milk.";

Is there a way of declaring a range of an array as an enumeration?

โŒ
โŒ