❌ About FreshRSS

Normal view

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

Wrap-around Semantics for accessing Array Slices indexed by a Modular Type

I would like to create an array and access it in the following way for read and write slice operations (i.e. more than one element at once):

  • If the indices are within range access them as usual
  • If the second index is smaller than the first index, access the data as follows: First .. A'Last & A'First .. (First + 5) (turns out this doesn't work as-is due to concatenation result upper bound out of range)

I have come up with the following example to demonstrate the issue:

with Ada.Text_IO;
use  Ada.Text_IO;

procedure Test_Modular is
    type Idx is mod 10;
    type My_Array is array (Idx range <>) of Integer;

    A: My_Array(Idx) := (
        0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5,
        6 => 6, 7 => 7, 8 => 8, 9 => 9
    );

    First: constant Idx := 7;

    S: constant My_Array := A(First .. First + 5);
begin

    for I in S'range loop
        Put_Line(Idx'Image(I) & " --> " & Integer'Image(S(I)));
    end loop;

end Test_Modular;

As in the example, the 5 is static, the compiler warns me as follows:

$ gnatmake -o test_modular test_modular.adb
x86_64-linux-gnu-gcc-10 -c test_modular.adb
test_modular.adb:18:19: warning: loop range is null, loop will not execute
x86_64-linux-gnu-gnatbind-10 -x test_modular.ali
x86_64-linux-gnu-gnatlink-10 test_modular.ali -o test_modular

When running the program, I observe the following:

$ ./test_modular

i.e. no output as predicted by the compiler warning.

Now I wonder: Is there a way to write the slice like A(First .. First + 5) and make it β€œwrap around” such that the data accessed will be the same as in this modified example program except without having to distinguish the two cases in the code explicitly?

with Ada.Text_IO;
use  Ada.Text_IO;

procedure Test_Modular_2 is
    type Idx is mod 10;
    type My_Array is array (Idx range <>) of Integer;

    A: My_Array(Idx) := (
        0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5,
        6 => 6, 7 => 7, 8 => 8, 9 => 9
    );

    First: constant Idx := 7;

    S1: constant My_Array := A(First .. A'Last);
    S2: constant My_Array := A(A'First .. (First + 5));
begin

    for I in S1'range loop
        Put_Line(Idx'Image(I) & " --> " & Integer'Image(S1(I)));
    end loop;
    for I in S2'range loop
        Put_Line(Idx'Image(I) & " --> " & Integer'Image(S2(I)));
    end loop;

end Test_Modular_2;
❌
❌