Hi,
I don’t understand how limitations on type and subtype constraints work. I used to think instanciation of unbounded arrays were forbidden, but not the declaration of type, except for constants whole value is known at compile-time, as is the case below.
pragma Ada_2022;
pragma Extensions_Allowed (On);
with Ada.Text_IO; use Ada.Text_IO;
procedure DISPLAY_INITIALS is
type Letters is array (1..8) of String;
M : constant Letters :=
["* *",
"** **",
"* * * *",
"* * * *",
"* * * *",
"* * * *",
"* * * *",
"* * *"];
S : constant Letters :=
["***************",
"* *",
"* *",
"* *",
"***************",
" *",
" *",
"***************"];
begin
for LINE of Letters'[for I in Letters'range => S(I) & M(I)] loop
PUT_LINE(LINE);
end loop;
end;
I could use add a constraint on the number of column, but then the aggregate at the end would fail.
The only solution I found is
type Big_Letters is array (1..8) of String(1..33);
type Letters is array (1..8) of String(1..15);
and then:
for LINE of Big_Letters'[for I in Letters'range => S(I) & " " & M(I)] loop
But it’s so clunky. Can’t the compiler create bounded anonymous subtypes for the constants and aggregate, considering they are all static variables ?
Why is defining the Letters type without constraints an issue, but an unbounded subtype of String isn’t ?
And I’m not sure I get why I need to qualify the aggregate at all while I usually don’t for say, a sequence of Integer.
Your declaration of Letters is not valid Ada. Either your compiler has an error, or you’re using a compiler for another language that looks a lot like Ada. pragma Extensions_Allowed (On); implies the latter.
Of course it’s Ada… compiler is GNAT 13.3.0.
Ah ok, so declarations of arrays of unconstrained components are not allowed. Same for records I suppose ?
And am I right that
Doesn’t require a qualified expression because it is being assigned to a variable with a known type (Integer_Array), so it knows exactly how to formulate an object from that array aggregate.
for Line of [for I in 1..4 => I] loop
null;
end loop
There are no types here. Line doesn’t have a type and the array aggregate doesn’t have a type. What type is the compiler supposed to infer here? A 4 byte integer, an 8 byte integer, an integer only in the range of 1…4 or an integer with a much broader range that contains 1…4? Something needs to indicate the expected type for this to work. Ada 2022 adds some syntax to help:
for Line : Integer of [for I in 1..4 => I] loop
null;
end loop
But it is a new feature and GNAT still has issues unless you do the qualified expression for the aggregate. I don’t know if this is a compiler bug with the new feature or a language bug, but with they type qualification of Line, that should technically be enough to determine the type. Maybe worth generating a question to Adacore to see if intended or a bug and if intended what is the thought process / language req?
Ok, I think I got it now, you made sense.
However, according to you the following should not be rejected, even though it is
for LINE : String of [for I in Letters'range => S(I) & M(I)] loop
PUT_LINE(LINE);
end loop;
The type of Line and the type of the aggregate, and their boundaries, are obvious and inferable. I get display_initials.adb:26:27: error: name expected. Should I use gnat’s github, or is someone here in better position to tell them ?
Yes. Though keep in mind that I may just be naive in thinking that is ok, but my first impression is that should be enough to allow type inference. GNAT has a bugzilla interface through GCC
If you have a github account, you can maybe make an issue or send a message on their github for it.
Alternately you can maybe send an email to Adacore support to ask. I was trying to find the email for that, but can’t seem to locate it (it’s been years since I used it). Maybe someone here has it handy.