❌ About FreshRSS

Reading view

There are new articles available, click to refresh the page.

Ada2012: Assertion_Policy

According Ada2012 RM Assertion_Policy:

10.2/3 A pragma Assertion_Policy applies to the named assertion aspects in a specific region, and applies to all assertion expressions specified in that region. A pragma Assertion_Policy given in a declarative_part or immediately within a package_specification applies from the place of the pragma to the end of the innermost enclosing declarative region. The region for a pragma Assertion_Policy given as a configuration pragma is the declarative region for the entire compilation unit (or units) to which it applies.

This means that if I have a package hierarchy as per the following example:

└───Root
    β”œβ”€β”€β”€Child1
    β”œβ”€β”€β”€Child2
    β”‚   └───GrandSon
    └───Child3

And if I define the pragma Assertion_Policy at Root package specification, it will affect to the whole package hierarchy right?

Penultimate array index retrieval

Suppose the following generic procedure to print the elements of an array indexed by a discreet type (note the slight logic added to prevent the printing of an extra , past the end of the last element):

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Array_Printer is
   
   generic
      type Index is (<>);
      type Int_Array is array (Index range <>) of Integer;
   procedure Print(IA: Int_Array); 
   
   procedure Print(IA: Int_Array) is
      -- Penultimate: Index := Index'Pred(IA'Last); -- raises CONSTRAINT_ERROR for IA'Length = 1
   begin
      Put("[");
      for I in IA'First .. Index'Pred(IA'Last) loop
         Put(IA(I), 0);Put(",");
      end loop;
      Put(IA(IA'Last), 0);
      Put("]");      
   end Print;
   
   type Int_Array is array(Positive range <>) of Integer;
   
   IA: Int_Array := (-3, -2, -1, 0, 1, 2, 3);
   IA2: Int_Array := (1 => 0);
   
   procedure Print_Int_Array is new Print(Index => Positive,
                                          Int_Array => Int_Array);
   
   begin
      Print_Int_Array(IA);   
end Array_Printer;

When this procedure runs with an array of length > 1 (e.g. IA) it correctly prints the array ([-3,-2,-1,0,1,2,3]). However, when it is given an array of length = 1 (e.g. IA2) then, perhaps surprisingly, the penultimate index calculation in the for-loop doesn't raise a CONSTRAINT_ERROR (due to a predecessor not existing) and the expected result ([0]) gets printed.

When that calculation is done elsewhere however (e.g. in the declarative section of the procedure) then that exception is raised, indeed.

Is the compiler smart enough to figure-out there's only one element in the array and hence generates a null range for the for loop?

Gnatstudio seems to be invoking gprbuild with -cargs -g -O0

Any thoughts? - Thanks

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;

Type conversions and if expressions

In this page, John Barnes writes:

If the conditional expression is the argument of a type conversion then effectively the conversion is considered pushed down to the dependent expressions. Thus

X := Float(if P then A else B);

is equivalent to

X := (if P then Float(A) else Float(B));

So why can't I compile the following program under GNAT 10.3.0?

procedure Main is
   P : Boolean := True;
   X : Float;
begin
   X := Float (if P then 0.5 else 32);
end Main;
Compile
   [Ada]          main.adb
main.adb:5:35: expected a real type
main.adb:5:35: found type universal integer
gprbuild: *** compilation phase failed
❌