I'm trying to use the 'for cursor in container.first loop' syntax in Ada
2012 with my own container, and having lots of problems.
So first I tried a simple example using Ada.Containers.Vector, with GNAT
2014:
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Containers.Vectors;
procedure Try_Containers
is
package Integer_Vectors is new Ada.Containers.Vectors (Natural, Integer);
use Integer_Vectors;
A : Vector := To_Vector (1, 10);
begin
Loop_1 :
for Element of A loop
Put_Line ("A (i) => " & Integer'Image (Element));
-- can't do Element := 2;
end loop Loop_1;
Loop_2 :
for Cursor in First (A) loop
Put_Line ("A (I) => " & Integer'Image (Element (Cursor)));
Replace_Element (A, Cursor, 2);
Reference (A, Cursor) := 2;
end loop Loop_2;
end Try_Containers;
This gives compilation errors:
gnatmake -k ../try_containers.adb
gcc -c -I../ -I- ../try_containers.adb
try_containers.adb:17:28: invalid prefix in call
try_containers.adb:17:28: invalid prefix in selected component "I572b"
gnatmake: "../try_containers.adb" compilation error
Same error (with a different generated name) with GnatPro 7.2.
Commenting out loop_2 gives the expected results.
Am I missing something simple, or is this a compiler bug? At the very
least, it's not a good error message.
--
-- Stephe
Simon Wright writes:
> While scratching my head over 5.5.2 Generalized Loop Iteration, I looked
> at A.18.32 Example of Container Use[1] and tried compiling with GNAT GPL
> 2014 and GCC 4.9.0. The full example compiled fine, but when I attempted
> the substitution in (29) this happened:
>
> 65. for C in G (Next).Iterate loop
> 66. declare
> 67. E : Edge renames G (Next)(C).all;
> |
> >>> access type required in prefix of explicit dereference
This should be:
E : Edge renames Element (C);
Randy, can you take it from here, or do we need to submit an Ada
Comment?
--
-- Stephe
"Randy Brukardt" writes:
> "Stephen Leake" wrote in message
> news:85y4u8xztj.fsf@stephe-leake.org...
>>
>> Loop_2 :
>> for Cursor in First (A) loop
>> Put_Line ("A (I) => " & Integer'Image (Element (Cursor)));
>> Replace_Element (A, Cursor, 2);
>> Reference (A, Cursor) := 2;
>> end loop Loop_2;
>>
>> gnatmake -k ../try_containers.adb
>> gcc -c -I../ -I- ../try_containers.adb
>> try_containers.adb:17:28: invalid prefix in call
>> try_containers.adb:17:28: invalid prefix in selected component "I572b"
>>
>> Am I missing something simple, or is this a compiler bug? At the very
>> least, it's not a good error message.
>
> You're missing something simple: "First" is not an iterator (it returns a
> cursor). You need to use one of the functions named "Iterate" that return a
> value that has an iterator type:
>
> Loop_2 :
> for Cursor in Iterate (A) loop
Ah, thanks. That fixed it.
> I'd still call it a bug, though, because the error message is inpenatrable
> for something simple (a violation of 5.5.2(3/3)). Indeed, this shouldn't
> even resolve.
I'll report it.
--
-- Stephe
"Simon Wright" wrote in message
news:lyfvggibpz.fsf@pushface.org...
> While scratching my head over 5.5.2 Generalized Loop Iteration, I looked
> at A.18.32 Example of Container Use[1] and tried compiling with GNAT GPL
> 2014 and GCC 4.9.0. The full example compiled fine, but when I attempted
> the substitution in (29) this happened:
Yes, this is known. Had you used the bleeding edge RM
(http://www.ada-auth.org/standards/ada2x.html) you would have noticed that
this example is one of many corrections to Ada 2012. (There is enough that
WG 9 has ordered us to produce a Corrigendum of fixes by the end of next
year.)
The story here is simply that your editor (that would me) had for some
reason gotten the wrong notion of how generalized references worked. He then
carefully used this wrong notion in RM examples and also in some examples
that he gave to John Barnes for use in the Rationale. Both the RM and the
Rationale required correction.
Specifically:
....
> 65. for C in G (Next).Iterate loop
> 66. declare
> 67. E : Edge renames G (Next)(C).all;
No .all here; this should be:
E : Edge renames G (Next)(C);
and the rest of the errors are a cascade.
There's an extra .all in A.18.32(31/4) as well.
Precisely why I was convinced that we needed that .all will have to remain a
mystery. The rules are clear enough. (Most likely, some of the examples I
posted here on cla probably had this misconception as well.)
Randy.
While scratching my head over 5.5.2 Generalized Loop Iteration, I looked
at A.18.32 Example of Container Use[1] and tried compiling with GNAT GPL
2014 and GCC 4.9.0. The full example compiled fine, but when I attempted
the substitution in (29) this happened:
55. -- Update minimum distance to newly reachable nodes.
56. for E of G (Next) loop
57. if not Reached(E.To) then
58. Nearest_Distance := E.Length + So_Far(Next);
59. if Nearest_Distance < So_Far(E.To) then
60. Reached_From(E.To) := Next;
61. So_Far(E.To) := Nearest_Distance;
62. end if;
63. end if;
64. end loop;
(so the original was OK, but ...)
65. for C in G (Next).Iterate loop
66. declare
67. E : Edge renames G (Next)(C).all;
|
>>> access type required in prefix of explicit dereference
68. begin
69. if not Reached(E.To) then
|
>>> invalid prefix in selected component "E"
70. Nearest_Distance := E.Length + So_Far(Next);
|
>>> invalid prefix in selected component "E"
71. if Nearest_Distance < So_Far(E.To) then
|
>>> invalid prefix in selected component "E"
72. Reached_From(E.To) := Next;
|
>>> invalid prefix in selected component "E"
73. So_Far(E.To) := Nearest_Distance;
|
>>> invalid prefix in selected component "E"
74. end if;
75. end if;
76. end;
77. end loop;
[1] http://www.ada-auth.org/standards/12rm/html/RM-A-18-32.html